93 lines
3.1 KiB
C#
93 lines
3.1 KiB
C#
using System.Collections;
|
||
using UnityEngine;
|
||
using UnityEngine.SceneManagement;
|
||
using BaseGames.Core.Events;
|
||
|
||
namespace BaseGames.Core
|
||
{
|
||
/// <summary>
|
||
/// 场景管理服务接口。
|
||
/// </summary>
|
||
public interface ISceneService
|
||
{
|
||
/// <summary>异步加载指定场景(Additive)。</summary>
|
||
IEnumerator LoadSceneCoroutine(SceneLoadRequest request);
|
||
/// <summary>卸载当前房间场景(保留 Persistent)。</summary>
|
||
IEnumerator UnloadCurrentRoomCoroutine();
|
||
/// <summary>加载主菜单。</summary>
|
||
IEnumerator LoadMainMenuCoroutine();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 场景管理服务(Phase 0 骨架,Phase 1 完整实现)。
|
||
/// </summary>
|
||
[DefaultExecutionOrder(-900)]
|
||
public class SceneService : MonoBehaviour, ISceneService
|
||
{
|
||
[Header("Event Channels - Listen")]
|
||
[SerializeField] private SceneLoadRequestEventChannelSO _onSceneLoadRequest;
|
||
|
||
[Header("Event Channels - Raise")]
|
||
[SerializeField] private StringEventChannelSO _onSceneLoaded;
|
||
[SerializeField] private VoidEventChannelSO _onFadeInRequest;
|
||
[SerializeField] private VoidEventChannelSO _onFadeOutRequest;
|
||
|
||
[SerializeField] private float _fadeDuration = 0.3f;
|
||
|
||
private string _currentRoomScene;
|
||
|
||
private void OnEnable()
|
||
{
|
||
if (_onSceneLoadRequest != null)
|
||
_onSceneLoadRequest.OnEventRaised += HandleSceneLoadRequest;
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
if (_onSceneLoadRequest != null)
|
||
_onSceneLoadRequest.OnEventRaised -= HandleSceneLoadRequest;
|
||
}
|
||
|
||
private void HandleSceneLoadRequest(SceneLoadRequest request)
|
||
=> StartCoroutine(LoadSceneCoroutine(request));
|
||
|
||
public IEnumerator LoadSceneCoroutine(SceneLoadRequest request)
|
||
{
|
||
_onFadeOutRequest?.Raise();
|
||
yield return new WaitForSeconds(_fadeDuration);
|
||
|
||
if (!string.IsNullOrEmpty(_currentRoomScene))
|
||
{
|
||
var unload = SceneManager.UnloadSceneAsync(_currentRoomScene);
|
||
yield return new WaitUntil(() => unload.isDone);
|
||
}
|
||
|
||
var load = SceneManager.LoadSceneAsync(request.SceneName, LoadSceneMode.Additive);
|
||
yield return new WaitUntil(() => load.isDone);
|
||
|
||
_currentRoomScene = request.SceneName;
|
||
_onSceneLoaded?.Raise(request.SceneName);
|
||
_onFadeInRequest?.Raise();
|
||
}
|
||
|
||
public IEnumerator UnloadCurrentRoomCoroutine()
|
||
{
|
||
if (string.IsNullOrEmpty(_currentRoomScene)) yield break;
|
||
var op = SceneManager.UnloadSceneAsync(_currentRoomScene);
|
||
yield return new WaitUntil(() => op.isDone);
|
||
_currentRoomScene = null;
|
||
}
|
||
|
||
public IEnumerator LoadMainMenuCoroutine()
|
||
{
|
||
yield return LoadSceneCoroutine(new SceneLoadRequest
|
||
{
|
||
SceneName = "MainMenu",
|
||
EntryTransitionId = null,
|
||
ShowLoadingScreen = false,
|
||
IsRespawn = false
|
||
});
|
||
}
|
||
}
|
||
}
|