using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Framework;
using Gameplay;
using Gameplay.Performance;
using Gameplay.SubSystems;
using PhxhSDK;
using PhxhSDK.Res;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using Constants = Framework.Constants;
///
/// 游戏场景的通用业务逻辑
///
public class GameSceneHelper : Singlenton
{
private Stack<(string, SceneHandle)> _uiViewSceneStack = new();
private RenderTexture _rTexture;
private Stack<(string, SceneHandle)> _rtSceneStack = new ();
///
/// 打开UI预览场景,当某个UI需要单独渲染场景时使用(如PVP布阵,营地等)
/// 该函数会使得预览场景中的相机只渲染UI场景内的物件
/// 并处理了光照,全局GI,Volume,单一主相机
///
///
///
public async UniTask LoadSceneForUIView(string scenePath,
LoadSceneMode loadSceneMode = LoadSceneMode.Additive)
{
// DebugUtil.Log($"加载UIView场景:{scenePath}");
SceneHandle sceneHandle = await GameSceneManager.Instance.LoadSceneAsync(scenePath, loadSceneMode);
if (sceneHandle == null)
return null;
if (loadSceneMode == LoadSceneMode.Additive)
{
if (_uiViewSceneStack.Count > 0)
{
//如果之前加载过UIView场景,则使得上一个场景不影响当前场景
(string, SceneHandle) lastUIViewSceneData = _uiViewSceneStack.Peek();
SetSceneActiveForUIView(lastUIViewSceneData.Item2, false);
}
}
else
_uiViewSceneStack.Clear();
SetSceneActiveForUIView(sceneHandle, true);
_uiViewSceneStack.Push((scenePath, sceneHandle));
return sceneHandle;
}
///
/// 卸载场景
///
///
public async UniTask UnloadSceneForUIView()
{
if (_uiViewSceneStack.Count == 0)
{
DebugUtil.LogError($"没有加载过UIView场景");
return;
}
(string, SceneHandle) sceneData = _uiViewSceneStack.Pop();
CameraManager.Instance.RevertMainCamera();
await GameSceneManager.Instance.UnLoadSceneAsync(sceneData.Item1);
if (_uiViewSceneStack.Count > 0)
{
(string, SceneHandle) lastUIViewSceneData = _uiViewSceneStack.Peek();
SetSceneActiveForUIView(lastUIViewSceneData.Item2, true);
}
}
///
/// 设置激活场景
///
///
///
public void SetSceneActiveForUIView(SceneHandle sceneHandle, bool isActive)
{
Scene scene = sceneHandle.Scene;
if (!scene.IsValid())
return;
int groundLayer = Constants.Layer.GROUND;
int layerToSet = isActive ? Constants.Layer.UIVIEW : Constants.Layer.DEFAULT;
int maskToSet = isActive ? LayerMask.GetMask(Constants.Layer.UIVIEW_NAME, Constants.Layer.GROUND_NAME) :
LayerMask.GetMask(Constants.Layer.DEFAULT_NAME, Constants.Layer.GROUND_NAME);
//调整所有物品的层级
GameObject[] roots = scene.GetRootGameObjects();
foreach (GameObject root in roots)
{
//将所有gameObject设置为UIView层
root.SetLayerEx(layerToSet, groundLayer);
root.SetActive(isActive);
}
Volume volume = sceneHandle.GetSceneVolume();
if (volume != null)
volume.enabled = isActive;
Camera sceneMainCamera = sceneHandle.SceneMainCamera;
if (sceneMainCamera != null)
{
var additionalData = sceneMainCamera.GetUniversalAdditionalCameraData();
sceneMainCamera.cullingMask = maskToSet;
//volume处理
additionalData.volumeLayerMask = maskToSet;
}
//设置光源culling mask
var lights = Object.FindObjectsOfType();
foreach (var light in lights)
{
if (light.gameObject.scene != scene)
continue;
light.cullingMask = maskToSet;
}
if (isActive)
{
//切换全局GI
SceneManager.SetActiveScene(scene);
//切换主相机
CameraManager.Instance.SwitchMainCamera(sceneMainCamera);
}
}
public RenderTexture GetRenderTexture()
{
if (!_rTexture)
{
_CreateRt();
}
return _rTexture;
}
private void _CreateRt()
{
_rTexture = RenderTexturePool.Instance.Create("GameSceneHelper_rt", PerformanceManager.instance.fullScreenWidth,
PerformanceManager.instance.fullScreenHeight);
}
private void _ReleaseRt()
{
if (_rTexture)
{
RenderTexturePool.Instance.Destroy(_rTexture);
_rTexture = null;
}
}
///
/// 获取当前显示的场景
///
///
public SceneHandle GetCurrentUIViewScene()
{
if (_uiViewSceneStack.Count == 0)
return null;
return _uiViewSceneStack.Peek().Item2;
}
///
/// 切换当前显示的场景
///
///
///
///
public void ChangeSceneForUIView(string scenePath)
{
if (_uiViewSceneStack.Count <= 0)
{
DebugUtil.LogError("当前没有场景");
return;
}
Stack<(string, SceneHandle)> stackTemp = new();
SceneHandle curSceneHandle = null; // 要激活的场景
#region 校验当前场景是否是要切换的场景
(string, SceneHandle) lastUIViewScene = _uiViewSceneStack.Pop(); // 当前激活场景
if (lastUIViewScene.Item1.Equals(scenePath))
{
DebugUtil.LogWarning($"已经激活该场景{scenePath}");
_uiViewSceneStack.Push(lastUIViewScene);
return;
}
#endregion
#region 遍历剩下的所有场景,获取要切换的场景,其余场景临时存起来
while (_uiViewSceneStack.Count > 0)
{
(string, SceneHandle) uiViewScene = _uiViewSceneStack.Pop();
if (uiViewScene.Item1.Equals(scenePath))
{
curSceneHandle = uiViewScene.Item2;
break;
}
else
stackTemp.Push(uiViewScene);
}
#endregion
#region 先把临时存的场景放回栈中
while (stackTemp.Count > 0)
{
_uiViewSceneStack.Push(stackTemp.Pop());
}
#endregion
_uiViewSceneStack.Push(lastUIViewScene); // 放入上次激活的场景
if (curSceneHandle != null)
{
_uiViewSceneStack.Push((scenePath, curSceneHandle));
SetSceneActiveForUIView(lastUIViewScene.Item2, false);
SetSceneActiveForUIView(curSceneHandle, true);
}
else
DebugUtil.LogError($"没有加载场景{scenePath}");
}
public async UniTask LoadSceneForRt(string scenePath)
{
var sceneHandle = await GameSceneManager.Instance.LoadSceneAsync(scenePath, LoadSceneMode.Additive);
if (sceneHandle == null)
{
return null;
}
var sceneCamera = sceneHandle.SceneMainCamera;
var rTexture = GetRenderTexture();
sceneCamera.targetTexture = rTexture;
_rtSceneStack.Push((scenePath, sceneHandle));
return sceneHandle;
}
public async UniTask UnLoadSceneForRt()
{
if (_rtSceneStack.Count > 0)
{
var item = _rtSceneStack.Pop();
await GameSceneManager.Instance.UnLoadSceneAsync(item.Item1);
_ReleaseRt();
}
}
}