NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/SubSystems/GameSceneHelper.cs

146 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System.Collections;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Gameplay;
using Gameplay.SubSystems;
using PhxhSDK;
using PhxhSDK.Res;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
/// <summary>
/// 游戏场景的通用业务逻辑
/// </summary>
public class GameSceneHelper : Singlenton<GameSceneHelper>
{
private Stack<(string, SceneHandle)> _uiViewSceneStack = new();
/// <summary>
/// 打开UI预览场景当某个UI需要单独渲染场景时使用(如PVP布阵营地等)
/// 该函数会使得预览场景中的相机只渲染UI场景内的物件
/// 并处理了光照全局GIVolume单一主相机
/// </summary>
/// <param name="scenePath"></param>
/// <returns></returns>
public async UniTask<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();
CameraManager.Instance.RevertMainCamera();
await GameSceneManager.Instance.UnLoadSceneAsync(sceneData.Item1);
if (_uiViewSceneStack.Count > 0)
{
var lastUIViewSceneData = _uiViewSceneStack.Peek();
SetSceneActiveForUIView(lastUIViewSceneData.Item2, true);
}
}
private void SetSceneActiveForUIView(SceneHandle sceneHandle,
bool isActive)
{
var scene = sceneHandle.Scene;
if (!scene.IsValid())
{
return;
}
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 SceneHandle GetCurrentUIViewScene()
{
if (_uiViewSceneStack.Count == 0)
return null;
return _uiViewSceneStack.Peek().Item2;
}
public async UniTask ChangeSceneForUIView(string scenePath, LoadSceneMode loadSceneMode = LoadSceneMode.Single)
{
if (_uiViewSceneStack.Count > 0)
{
var uiViewScene = _uiViewSceneStack.Pop();
var sceneHandle = await GameSceneManager.Instance.LoadSceneAsync(scenePath, loadSceneMode);
if (sceneHandle == null)
{
return;
}
_uiViewSceneStack.Push((scenePath, sceneHandle));
}
}
}