SceneInterestManagement.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.SceneManagement;
  4. namespace Mirror
  5. {
  6. [AddComponentMenu("Network/ Interest Management/ Scene/Scene Interest Management")]
  7. public class SceneInterestManagement : InterestManagement
  8. {
  9. // Use Scene instead of string scene.name because when additively
  10. // loading multiples of a subscene the name won't be unique
  11. readonly Dictionary<Scene, HashSet<NetworkIdentity>> sceneObjects =
  12. new Dictionary<Scene, HashSet<NetworkIdentity>>();
  13. readonly Dictionary<NetworkIdentity, Scene> lastObjectScene =
  14. new Dictionary<NetworkIdentity, Scene>();
  15. HashSet<Scene> dirtyScenes = new HashSet<Scene>();
  16. public override void OnSpawned(NetworkIdentity identity)
  17. {
  18. Scene currentScene = identity.gameObject.scene;
  19. lastObjectScene[identity] = currentScene;
  20. // Debug.Log($"SceneInterestManagement.OnSpawned({identity.name}) currentScene: {currentScene}");
  21. if (!sceneObjects.TryGetValue(currentScene, out HashSet<NetworkIdentity> objects))
  22. {
  23. objects = new HashSet<NetworkIdentity>();
  24. sceneObjects.Add(currentScene, objects);
  25. }
  26. objects.Add(identity);
  27. }
  28. public override void OnDestroyed(NetworkIdentity identity)
  29. {
  30. Scene currentScene = lastObjectScene[identity];
  31. lastObjectScene.Remove(identity);
  32. if (sceneObjects.TryGetValue(currentScene, out HashSet<NetworkIdentity> objects) && objects.Remove(identity))
  33. RebuildSceneObservers(currentScene);
  34. }
  35. // internal so we can update from tests
  36. [ServerCallback]
  37. internal void Update()
  38. {
  39. // for each spawned:
  40. // if scene changed:
  41. // add previous to dirty
  42. // add new to dirty
  43. foreach (NetworkIdentity identity in NetworkServer.spawned.Values)
  44. {
  45. Scene currentScene = lastObjectScene[identity];
  46. Scene newScene = identity.gameObject.scene;
  47. if (newScene == currentScene)
  48. continue;
  49. // Mark new/old scenes as dirty so they get rebuilt
  50. dirtyScenes.Add(currentScene);
  51. dirtyScenes.Add(newScene);
  52. // This object is in a new scene so observers in the prior scene
  53. // and the new scene need to rebuild their respective observers lists.
  54. // Remove this object from the hashset of the scene it just left
  55. sceneObjects[currentScene].Remove(identity);
  56. // Set this to the new scene this object just entered
  57. lastObjectScene[identity] = newScene;
  58. // Make sure this new scene is in the dictionary
  59. if (!sceneObjects.ContainsKey(newScene))
  60. sceneObjects.Add(newScene, new HashSet<NetworkIdentity>());
  61. // Add this object to the hashset of the new scene
  62. sceneObjects[newScene].Add(identity);
  63. }
  64. // rebuild all dirty scenes
  65. foreach (Scene dirtyScene in dirtyScenes)
  66. RebuildSceneObservers(dirtyScene);
  67. dirtyScenes.Clear();
  68. }
  69. void RebuildSceneObservers(Scene scene)
  70. {
  71. foreach (NetworkIdentity netIdentity in sceneObjects[scene])
  72. if (netIdentity != null)
  73. NetworkServer.RebuildObservers(netIdentity, false);
  74. }
  75. public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver)
  76. {
  77. return identity.gameObject.scene == newObserver.identity.gameObject.scene;
  78. }
  79. public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnectionToClient> newObservers)
  80. {
  81. if (!sceneObjects.TryGetValue(identity.gameObject.scene, out HashSet<NetworkIdentity> objects))
  82. return;
  83. // Add everything in the hashset for this object's current scene
  84. foreach (NetworkIdentity networkIdentity in objects)
  85. if (networkIdentity != null && networkIdentity.connectionToClient != null)
  86. newObservers.Add(networkIdentity.connectionToClient);
  87. }
  88. }
  89. }