108 lines
3.3 KiB
C#
108 lines
3.3 KiB
C#
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using Cysharp.Threading.Tasks;
|
|
using RebootKit.Engine.Foundation;
|
|
using RebootKit.Engine.Main;
|
|
using UnityEngine;
|
|
using UnityEngine.Assertions;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using UnityEngine.ResourceManagement.ResourceProviders;
|
|
using UnityEngine.SceneManagement;
|
|
using Logger = RebootKit.Engine.Foundation.Logger;
|
|
|
|
namespace RebootKit.Engine.Simulation {
|
|
public interface IWorldContext { }
|
|
|
|
public class WorldService : IService {
|
|
static readonly Logger s_Logger = new Logger(nameof(WorldService));
|
|
|
|
enum WorldState {
|
|
Unloaded,
|
|
Loading,
|
|
Loaded
|
|
}
|
|
|
|
WorldState m_WorldState = WorldState.Unloaded;
|
|
WorldConfig m_Config;
|
|
AsyncOperationHandle<SceneInstance> m_SceneInstance;
|
|
|
|
enum ActorOrigin {
|
|
InScene,
|
|
Prefab
|
|
}
|
|
|
|
struct ActorData {
|
|
public ActorOrigin Origin;
|
|
public Actor Actor;
|
|
|
|
public ActorData(ActorOrigin origin, Actor actor) {
|
|
Origin = origin;
|
|
Actor = actor;
|
|
}
|
|
}
|
|
|
|
readonly List<ActorData> m_Actors = new List<ActorData>();
|
|
|
|
public IWorldContext Context { get; private set; }
|
|
|
|
public string WorldID {
|
|
get {
|
|
return string.IsNullOrEmpty(m_Config.name) ? string.Empty : m_Config.name;
|
|
}
|
|
}
|
|
|
|
public WorldService() {
|
|
}
|
|
|
|
public void Dispose() {
|
|
Unload();
|
|
}
|
|
|
|
public async UniTask LoadAsync(WorldConfig worldConfig, CancellationToken cancellationToken) {
|
|
await UniTask.WaitWhile(() => m_WorldState == WorldState.Loading, cancellationToken: cancellationToken);
|
|
|
|
Unload();
|
|
|
|
m_WorldState = WorldState.Loading;
|
|
m_Config = worldConfig;
|
|
|
|
m_SceneInstance = worldConfig.mainScene.LoadSceneAsync(LoadSceneMode.Additive, false);
|
|
await m_SceneInstance.ToUniTask(cancellationToken: cancellationToken);
|
|
|
|
await m_SceneInstance.Result.ActivateAsync();
|
|
SceneManager.SetActiveScene(m_SceneInstance.Result.Scene);
|
|
|
|
foreach (GameObject root in m_SceneInstance.Result.Scene.GetRootGameObjects()) {
|
|
if (root.TryGetComponent(out IWorldContext worldContext)) {
|
|
Assert.IsNull(Context,
|
|
"WorldContext is already set. There should be only one WorldContext in the scene.");
|
|
Context = worldContext;
|
|
}
|
|
|
|
foreach (Actor actor in root.GetComponentsInChildren<Actor>()) {
|
|
RR.Network.Actors.RegisterInSceneActor(actor);
|
|
}
|
|
}
|
|
|
|
m_WorldState = WorldState.Loaded;
|
|
}
|
|
|
|
public void Unload() {
|
|
if (m_WorldState == WorldState.Unloaded) {
|
|
return;
|
|
}
|
|
|
|
if (RR.Network != null) {
|
|
RR.Network.Actors.CleanUp();
|
|
}
|
|
|
|
if (m_SceneInstance.IsValid()) {
|
|
m_SceneInstance.Release();
|
|
m_SceneInstance = default;
|
|
}
|
|
|
|
m_WorldState = WorldState.Unloaded;
|
|
Context = null;
|
|
}
|
|
}
|
|
} |