-
Notifications
You must be signed in to change notification settings - Fork 450
refactor: decouple PendingSoftSyncObjects from NetworkSpawnManager #913
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4da4b22
cfe461a
70e07e8
d47281e
c2067fd
6466d6c
fdcaaea
bdfe6b5
ab30892
7b90aaf
34b33b7
83afebc
242ac60
c31e9a0
80c5f44
446b4d4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -79,6 +79,7 @@ public class NetworkSceneManager | |||||
internal readonly Dictionary<string, uint> SceneNameToIndex = new Dictionary<string, uint>(); | ||||||
internal readonly Dictionary<uint, string> SceneIndexToString = new Dictionary<uint, string>(); | ||||||
internal readonly Dictionary<Guid, SceneSwitchProgress> SceneSwitchProgresses = new Dictionary<Guid, SceneSwitchProgress>(); | ||||||
internal readonly Dictionary<uint, NetworkObject> ScenePlacedObjects = new Dictionary<uint, NetworkObject>(); | ||||||
|
||||||
private static Scene s_LastScene; | ||||||
private static string s_NextSceneName; | ||||||
|
@@ -273,12 +274,49 @@ internal void OnFirstSceneSwitchSync(uint sceneIndex, Guid switchSceneGuid) | |||||
s_IsSwitching = false; | ||||||
} | ||||||
|
||||||
|
||||||
|
||||||
|
||||||
/// <summary> | ||||||
/// Should be invoked on both the client and server side after: | ||||||
/// -- A new scene has been loaded | ||||||
/// -- Before any "DontDestroyOnLoad" NetworkObjects have been added back into the scene. | ||||||
/// Added the ability to choose not to clear the scene placed objects for additive scene loading. | ||||||
/// </summary> | ||||||
internal void PopulateScenePlacedObjects(bool clearScenePlacedObjects = true) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor (personal opinion):
Suggested change
|
||||||
{ | ||||||
if (clearScenePlacedObjects) | ||||||
{ | ||||||
ScenePlacedObjects.Clear(); | ||||||
} | ||||||
|
||||||
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>(); | ||||||
|
||||||
// Just add every NetworkObject found that isn't already in the list | ||||||
// If any "non-in-scene placed NetworkObjects" are added to this list it shouldn't matter | ||||||
// The only thing that matters is making sure each NetworkObject is keyed off of their GlobalObjectIdHash | ||||||
foreach (var networkObjectInstance in networkObjects) | ||||||
{ | ||||||
if (!ScenePlacedObjects.ContainsKey(networkObjectInstance.GlobalObjectIdHash)) | ||||||
{ | ||||||
// We check to make sure the NetworkManager instance is the same one to be "MultiInstanceHelpers" compatible | ||||||
if (networkObjectInstance.IsSceneObject == null && networkObjectInstance.NetworkManager == m_NetworkManager) | ||||||
{ | ||||||
ScenePlacedObjects.Add(networkObjectInstance.GlobalObjectIdHash, networkObjectInstance); | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
private void OnSceneLoaded(Guid switchSceneGuid, Stream objectStream) | ||||||
{ | ||||||
CurrentActiveSceneIndex = SceneNameToIndex[s_NextSceneName]; | ||||||
var nextScene = SceneManager.GetSceneByName(s_NextSceneName); | ||||||
SceneManager.SetActiveScene(nextScene); | ||||||
|
||||||
//Get all NetworkObjects loaded by the scene | ||||||
PopulateScenePlacedObjects(); | ||||||
|
||||||
// Move all objects to the new scene | ||||||
MoveObjectsToScene(nextScene); | ||||||
|
||||||
|
@@ -288,31 +326,22 @@ private void OnSceneLoaded(Guid switchSceneGuid, Stream objectStream) | |||||
|
||||||
if (m_NetworkManager.IsServer) | ||||||
{ | ||||||
OnSceneUnloadServer(switchSceneGuid); | ||||||
OnServerLoadedScene(switchSceneGuid); | ||||||
} | ||||||
else | ||||||
{ | ||||||
OnSceneUnloadClient(switchSceneGuid, objectStream); | ||||||
OnClientLoadedScene(switchSceneGuid, objectStream); | ||||||
} | ||||||
} | ||||||
|
||||||
private void OnSceneUnloadServer(Guid switchSceneGuid) | ||||||
private void OnServerLoadedScene(Guid switchSceneGuid) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while you're doing some small refactors here, do you mind renaming all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will see if there is a better term for this... I ignored some of this stuff because the later phases of the proposal would effectively remove all of that. |
||||||
{ | ||||||
// Justification: Rare alloc, could(should?) reuse | ||||||
var newSceneObjects = new List<NetworkObject>(); | ||||||
// Register in-scene placed NetworkObjects with MLAPI | ||||||
foreach (var keyValuePair in ScenePlacedObjects) | ||||||
{ | ||||||
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>(); | ||||||
|
||||||
for (int i = 0; i < networkObjects.Length; i++) | ||||||
if (!keyValuePair.Value.IsPlayerObject) | ||||||
{ | ||||||
if (networkObjects[i].NetworkManager == m_NetworkManager) | ||||||
{ | ||||||
if (networkObjects[i].IsSceneObject == null) | ||||||
{ | ||||||
m_NetworkManager.SpawnManager.SpawnNetworkObjectLocally(networkObjects[i], m_NetworkManager.SpawnManager.GetNetworkObjectId(), true, false, null, null, false, 0, false, true); | ||||||
newSceneObjects.Add(networkObjects[i]); | ||||||
} | ||||||
} | ||||||
m_NetworkManager.SpawnManager.SpawnNetworkObjectLocally(keyValuePair.Value, m_NetworkManager.SpawnManager.GetNetworkObjectId(), true, false, null, null, false, 0, false, true); | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -327,25 +356,24 @@ private void OnSceneUnloadServer(Guid switchSceneGuid) | |||||
writer.WriteByteArray(switchSceneGuid.ToByteArray()); | ||||||
|
||||||
uint sceneObjectsToSpawn = 0; | ||||||
for (int i = 0; i < newSceneObjects.Count; i++) | ||||||
|
||||||
foreach (var keyValuePair in ScenePlacedObjects) | ||||||
{ | ||||||
if (newSceneObjects[i].Observers.Contains(m_NetworkManager.ConnectedClientsList[j].ClientId)) | ||||||
if (keyValuePair.Value.Observers.Contains(m_NetworkManager.ConnectedClientsList[j].ClientId)) | ||||||
{ | ||||||
sceneObjectsToSpawn++; | ||||||
} | ||||||
} | ||||||
|
||||||
// Write number of scene objects to spawn | ||||||
writer.WriteUInt32Packed(sceneObjectsToSpawn); | ||||||
|
||||||
for (int i = 0; i < newSceneObjects.Count; i++) | ||||||
foreach (var keyValuePair in ScenePlacedObjects) | ||||||
{ | ||||||
if (newSceneObjects[i].Observers.Contains(m_NetworkManager.ConnectedClientsList[j].ClientId)) | ||||||
if (keyValuePair.Value.Observers.Contains(m_NetworkManager.ConnectedClientsList[j].ClientId)) | ||||||
{ | ||||||
newSceneObjects[i].SerializeSceneObject(writer, m_NetworkManager.ConnectedClientsList[j].ClientId); | ||||||
keyValuePair.Value.SerializeSceneObject(writer, m_NetworkManager.ConnectedClientsList[j].ClientId); | ||||||
} | ||||||
} | ||||||
|
||||||
m_NetworkManager.MessageSender.Send(m_NetworkManager.ConnectedClientsList[j].ClientId, NetworkConstants.SWITCH_SCENE, NetworkChannel.Internal, buffer); | ||||||
} | ||||||
} | ||||||
|
@@ -362,12 +390,10 @@ private void OnSceneUnloadServer(Guid switchSceneGuid) | |||||
OnSceneSwitched?.Invoke(); | ||||||
} | ||||||
|
||||||
private void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStream) | ||||||
private void OnClientLoadedScene(Guid switchSceneGuid, Stream objectStream) | ||||||
{ | ||||||
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>(); | ||||||
|
||||||
m_NetworkManager.SpawnManager.ClientCollectSoftSyncSceneObjectSweep(networkObjects); | ||||||
|
||||||
using (var reader = PooledNetworkReader.Get(objectStream)) | ||||||
{ | ||||||
var newObjectsCount = reader.ReadUInt32Packed(); | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,9 +25,6 @@ public class NetworkSpawnManager | |
/// </summary> | ||
public readonly Dictionary<ulong, NetworkObject> SpawnedObjects = new Dictionary<ulong, NetworkObject>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we will eventually get rid of But obv, that's something for later — just wanted to braindump my 2-cents here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it is weird indeed. This update removes the dependency from NetworkSpawnManager and places it into NetworkSceneManager in preparation for the proposed direction. If we do go in the proposed general direction, then the object synchronization process will be handled differently anyway.... so keeping a list of in-scene NetworkObjects instantiated via scene loading really isn't "handling spawning"... it is just "tracking what was automatically instantiated". |
||
|
||
// Pending SoftSync objects | ||
internal readonly Dictionary<ulong, NetworkObject> PendingSoftSyncObjects = new Dictionary<ulong, NetworkObject>(); | ||
|
||
/// <summary> | ||
/// A list of the spawned objects | ||
/// </summary> | ||
|
@@ -246,17 +243,19 @@ internal NetworkObject CreateLocalNetworkObject(bool isSceneObject, uint globalO | |
} | ||
else | ||
{ | ||
// SoftSync them by mapping | ||
if (!PendingSoftSyncObjects.TryGetValue(globalObjectIdHash, out NetworkObject networkObject)) | ||
if (!NetworkManager.SceneManager.ScenePlacedObjects.TryGetValue(globalObjectIdHash, out NetworkObject networkObject)) | ||
{ | ||
if (NetworkLog.CurrentLogLevel <= LogLevel.Error) | ||
{ | ||
NetworkLog.LogError($"{nameof(NetworkPrefab)} hash was not found! In-Scene placed {nameof(NetworkObject)} soft synchronization failure for Hash: {globalObjectIdHash}!"); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
PendingSoftSyncObjects.Remove(globalObjectIdHash); | ||
else | ||
{ | ||
NetworkManager.SceneManager.ScenePlacedObjects.Remove(globalObjectIdHash); | ||
} | ||
|
||
if (parentNetworkObject != null) | ||
{ | ||
|
@@ -557,20 +556,6 @@ internal void DestroySceneObjects() | |
} | ||
} | ||
|
||
internal void CleanDiffedSceneObjects() | ||
{ | ||
// Clean up any in-scene objects that had been destroyed | ||
if (PendingSoftSyncObjects.Count > 0) | ||
{ | ||
foreach (var pair in PendingSoftSyncObjects) | ||
{ | ||
UnityEngine.Object.Destroy(pair.Value.gameObject); | ||
} | ||
|
||
// Make sure to clear this once done destroying all remaining NetworkObjects | ||
PendingSoftSyncObjects.Clear(); | ||
} | ||
} | ||
|
||
internal void ServerSpawnSceneObjectsOnStartSweep() | ||
{ | ||
|
@@ -588,25 +573,6 @@ internal void ServerSpawnSceneObjectsOnStartSweep() | |
} | ||
} | ||
|
||
internal void ClientCollectSoftSyncSceneObjectSweep(NetworkObject[] networkObjects) | ||
{ | ||
if (networkObjects == null) | ||
{ | ||
networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>(); | ||
} | ||
|
||
for (int i = 0; i < networkObjects.Length; i++) | ||
{ | ||
if (networkObjects[i].NetworkManager == NetworkManager) | ||
{ | ||
if (networkObjects[i].IsSceneObject == null) | ||
{ | ||
PendingSoftSyncObjects.Add(networkObjects[i].GlobalObjectIdHash, networkObjects[i]); | ||
} | ||
} | ||
} | ||
} | ||
|
||
internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObject) | ||
{ | ||
if (NetworkManager == null) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to be sure, this functions the same as the previous
PendingSoftSyncObjects
? So once a scene placed object get spawned it will be removed from this list? Maybe we should call thisPendingScenePlacedObjects
orUnspawnedScenePlacedObjects
if that is the case?