Files
RebootKit/Runtime/Engine/Code/Simulation/WorldService.cs
2025-07-30 05:51:39 +02:00

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;
}
}
}