119 lines
4.0 KiB
C#
119 lines
4.0 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using Cysharp.Threading.Tasks;
|
||
using Gameplay;
|
||
using Gameplay.SubSystems;
|
||
using PhxhSDK;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering;
|
||
using UnityEngine.Rendering.Universal;
|
||
using UnityEngine.SceneManagement;
|
||
|
||
/// <summary>
|
||
/// 游戏场景的通用业务逻辑
|
||
/// </summary>
|
||
public class GameSceneHelper : Singlenton<GameSceneHelper>
|
||
{
|
||
private Stack<(string, GameSceneManager.SceneHandle)> _uiViewSceneStack = new();
|
||
|
||
/// <summary>
|
||
/// 打开UI预览场景,当某个UI需要单独渲染场景时使用(如PVP布阵,营地等)
|
||
/// 该函数会使得预览场景中的相机只渲染UI场景内的物件
|
||
/// 并处理了光照,全局GI,Volume,单一主相机
|
||
/// </summary>
|
||
/// <param name="scenePath"></param>
|
||
/// <returns></returns>
|
||
public async UniTask<GameSceneManager.SceneHandle> LoadSceneForUIView(string scenePath, LoadSceneMode loadSceneMode = LoadSceneMode.Additive)
|
||
{
|
||
var sceneHandle = await GameSceneManager.Instance.LoadSceneAsync(scenePath, loadSceneMode);
|
||
if (sceneHandle == null)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
if (loadSceneMode == LoadSceneMode.Additive)
|
||
{
|
||
if (_uiViewSceneStack.Count > 0)
|
||
{
|
||
//如果之前加载过UIView场景,则使得上一个场景不影响当前场景
|
||
var 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;
|
||
}
|
||
|
||
var sceneData = _uiViewSceneStack.Pop();
|
||
await GameSceneManager.Instance.UnLoadSceneAsync(sceneData.Item1);
|
||
CameraManager.Instance.RevertMainCamera();
|
||
if (_uiViewSceneStack.Count > 0)
|
||
{
|
||
var lastUIViewSceneData = _uiViewSceneStack.Peek();
|
||
SetSceneActiveForUIView(lastUIViewSceneData.Item2, true);
|
||
}
|
||
}
|
||
|
||
private void SetSceneActiveForUIView(GameSceneManager.SceneHandle sceneHandle, bool isActive)
|
||
{
|
||
var scene = sceneHandle.Scene;
|
||
var groundLayer = LayerMask.NameToLayer("Ground");
|
||
var layerToSet = isActive ? LayerMask.NameToLayer("UIView") : LayerMask.NameToLayer("Default");
|
||
var maskToSet = isActive ? LayerMask.GetMask("UIView", "Ground") : LayerMask.GetMask("Default", "Ground");
|
||
//调整所有物品的层级
|
||
var roots = scene.GetRootGameObjects();
|
||
foreach (var root in roots)
|
||
{
|
||
//将所有gameObject设置为UIView层
|
||
root.SetLayerEx(layerToSet, groundLayer);
|
||
}
|
||
|
||
var sceneMainCamera = sceneHandle.SceneMainCamera;
|
||
if (sceneMainCamera != null)
|
||
{
|
||
var additionalData = sceneMainCamera.GetUniversalAdditionalCameraData();
|
||
sceneMainCamera.cullingMask = maskToSet;
|
||
//volume处理
|
||
additionalData.volumeLayerMask = maskToSet;
|
||
}
|
||
|
||
//设置光源culling mask
|
||
var lights = Object.FindObjectsOfType<Light>();
|
||
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 GameSceneManager.SceneHandle GetCurrentUIViewScene()
|
||
{
|
||
if (_uiViewSceneStack.Count == 0)
|
||
return null;
|
||
return _uiViewSceneStack.Peek().Item2;
|
||
}
|
||
} |