Mirror/Assets/Scenery/Bootstrap.cs

96 lines
3.4 KiB
C#
Raw Normal View History

2021-05-16 09:28:05 +00:00
// Bootstrap ServerWorld, ClientWorld just like in ECS.
using UnityEngine;
2021-05-16 07:55:39 +00:00
using UnityEngine.SceneManagement;
2021-05-16 07:10:31 +00:00
2021-05-16 09:28:05 +00:00
public class Bootstrap : MonoBehaviour
2021-05-16 07:10:31 +00:00
{
2021-05-16 07:55:39 +00:00
// Server/Client worlds for easy access
2021-05-16 09:27:27 +00:00
public static Scene ClientWorld;
public static Scene ServerWorld;
2021-05-16 09:28:52 +00:00
static bool initialized;
2021-05-16 07:55:39 +00:00
void Awake()
{
2021-05-16 09:27:27 +00:00
// we only do world initialization ONCE
// duplicating a scene would call Awake here again.
if (initialized) return;
initialized = true;
2021-05-16 10:04:09 +00:00
// original scene has to become the ClientWorld and it has to keep the
// same name. renaming it to ClientWorld would not load lighting data,
// and everything look pretty dark:
// https://forum.unity.com/threads/scenemanager-mergescenes-leaves-lighting-data.949203/
2021-05-16 10:07:29 +00:00
// TODO figure out how to load light data for modified scene name
2021-05-16 10:04:09 +00:00
ClientWorld = SceneManager.GetActiveScene();
2021-05-16 07:55:39 +00:00
2021-05-16 10:04:09 +00:00
// create a scene with [ServerWorld] suffix
string serverWorldName = ClientWorld.name + " [ServerWorld]";
2021-05-16 10:48:27 +00:00
// need a separate physics scene so ClientWorld objects don't call
// ServerWorld object's OnTrigger/OnCollision
// TODO 2D? via '|'?
CreateSceneParameters parameters = new CreateSceneParameters(LocalPhysicsMode.Physics3D);
SceneManager.CreateScene(serverWorldName, parameters);
2021-05-16 10:04:09 +00:00
ServerWorld = SceneManager.GetSceneByName(serverWorldName);
2021-05-16 07:55:39 +00:00
// can't merge any scenes yet because not loaded in Awake() yet.
// setup OnSceneLoaded callback and continue there.
SceneManager.sceneLoaded += OnSceneLoaded;
2021-05-16 09:27:27 +00:00
// duplicate original scene. we'll move it into ClientWorld
// -> additive, otherwise we would just reload it
2021-05-16 10:04:09 +00:00
SceneManager.LoadScene(ClientWorld.path, LoadSceneMode.Additive);
2021-05-16 07:55:39 +00:00
}
2021-05-16 10:04:09 +00:00
// helper function to remove all components in a scene
static void RemoveAll<T>(Scene scene) where T : Component
2021-05-16 09:42:25 +00:00
{
2021-05-16 10:04:09 +00:00
foreach (T component in FindObjectsOfType<T>())
if (component.gameObject.scene == scene)
Destroy(component);
}
2021-05-16 09:42:25 +00:00
2021-05-16 10:04:09 +00:00
// remove audio listener and main camera from server world
static void Strip(Scene scene)
{
Debug.Log($"Bootstrap: stripping {scene.name}");
2021-05-16 09:50:16 +00:00
2021-05-16 10:52:22 +00:00
// remove critical components
RemoveAll<Bootstrap>(scene);
2021-05-16 10:04:09 +00:00
RemoveAll<AudioListener>(scene);
RemoveAll<Camera>(scene);
RemoveAll<Light>(scene);
2021-05-16 10:24:22 +00:00
RemoveAll<Renderer>(scene);
2021-05-16 09:42:25 +00:00
}
2021-05-16 07:55:39 +00:00
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
2021-05-16 09:50:16 +00:00
Debug.Log($"OnSceneLoaded: {scene.name} {scene.path}");
2021-05-16 09:27:27 +00:00
2021-05-16 10:04:09 +00:00
// is this the original scene?
if (scene == ClientWorld)
2021-05-16 07:55:39 +00:00
{
2021-05-16 10:04:09 +00:00
Debug.Log($"original scene loaded");
2021-05-16 09:27:27 +00:00
}
2021-05-16 10:20:04 +00:00
// additive & not the same scene, but same path so it's the duplicate.
else if (mode == LoadSceneMode.Additive && scene.path == ClientWorld.path)
2021-05-16 09:27:27 +00:00
{
2021-05-16 10:04:09 +00:00
Debug.Log($"duplicated scene loaded");
// merge the duplicate into it
2021-05-16 09:50:16 +00:00
SceneManager.MergeScenes(scene, ServerWorld);
2021-05-16 10:04:09 +00:00
Debug.Log($"Bootstrap: duplicate scene merged into {ServerWorld.name}!");
// strip it
Strip(ServerWorld);
2021-05-16 07:55:39 +00:00
}
}
2021-05-16 10:53:40 +00:00
void FixedUpdate()
{
// then simulate physics in our server physics scene too
// TODO 2D?
ServerWorld.GetPhysicsScene().Simulate(Time.fixedDeltaTime);
}
2021-05-16 07:10:31 +00:00
}