@@ -1596,6 +1596,12 @@ private void OnDestroy()
15961596 if ( NetworkManager . IsListening && ! isAuthority && IsSpawned &&
15971597 ( IsSceneObject == null || ( IsSceneObject . Value != true ) ) )
15981598 {
1599+ // If we destroyed a GameObject with a NetworkObject component on the non-authority side, handle cleaning up the SceneMigrationSynchronization.
1600+ if ( SceneMigrationSynchronization && NetworkManager . NetworkConfig . EnableSceneManagement )
1601+ {
1602+ RemoveNetworkObjectFromSceneChangedUpdates ( this ) ;
1603+ }
1604+
15991605 // Clients should not despawn NetworkObjects while connected to a session, but we don't want to destroy the current call stack
16001606 // if this happens. Instead, we should just generate a network log error and exit early (as long as we are not shutting down).
16011607 if ( ! NetworkManager . ShutdownInProgress )
@@ -3264,6 +3270,13 @@ internal void SceneChangedUpdate(Scene scene, bool notify = false)
32643270 }
32653271
32663272 internal static Dictionary < ulong , NetworkObject > NetworkObjectsToSynchronizeSceneChanges = new Dictionary < ulong , NetworkObject > ( ) ;
3273+ internal static List < ulong > CleanUpDisposedObjects = new List < ulong > ( ) ;
3274+
3275+ internal static void CleanNetworkObjectSynchronization ( )
3276+ {
3277+ NetworkObjectsToSynchronizeSceneChanges . Clear ( ) ;
3278+ CleanUpDisposedObjects . Clear ( ) ;
3279+ }
32673280
32683281 internal static void AddNetworkObjectToSceneChangedUpdates ( NetworkObject networkObject )
32693282 {
@@ -3277,7 +3290,10 @@ internal static void AddNetworkObjectToSceneChangedUpdates(NetworkObject network
32773290
32783291 internal static void RemoveNetworkObjectFromSceneChangedUpdates ( NetworkObject networkObject )
32793292 {
3280- NetworkObjectsToSynchronizeSceneChanges . Remove ( networkObject . NetworkObjectId ) ;
3293+ if ( NetworkObjectsToSynchronizeSceneChanges . ContainsKey ( networkObject . NetworkObjectId ) )
3294+ {
3295+ NetworkObjectsToSynchronizeSceneChanges . Remove ( networkObject . NetworkObjectId ) ;
3296+ }
32813297 }
32823298
32833299 internal static void UpdateNetworkObjectSceneChanges ( )
@@ -3286,6 +3302,19 @@ internal static void UpdateNetworkObjectSceneChanges()
32863302 {
32873303 entry . Value . UpdateForSceneChanges ( ) ;
32883304 }
3305+
3306+ // Exit early if there is nothing to clean up
3307+ if ( CleanUpDisposedObjects . Count == 0 )
3308+ {
3309+ return ;
3310+ }
3311+
3312+ // Clean up any NetworkObjects that no longer exist (destroyed before they should be or the like)
3313+ foreach ( var networkObjectId in CleanUpDisposedObjects )
3314+ {
3315+ NetworkObjectsToSynchronizeSceneChanges . Remove ( networkObjectId ) ;
3316+ }
3317+ CleanUpDisposedObjects . Clear ( ) ;
32893318 }
32903319
32913320 private void Awake ( )
@@ -3316,8 +3345,14 @@ internal void UpdateForSceneChanges()
33163345 // the NetworkManager is shutting down, the NetworkObject is not spawned, it is an in-scene placed
33173346 // NetworkObject, or the GameObject's current scene handle is the same as the SceneOriginHandle
33183347 if ( ! SceneMigrationSynchronization || ! IsSpawned || NetworkManager == null || NetworkManager . ShutdownInProgress ||
3319- ! NetworkManager . NetworkConfig . EnableSceneManagement || IsSceneObject != false || gameObject . scene . handle == SceneOriginHandle )
3348+ ! NetworkManager . NetworkConfig . EnableSceneManagement || IsSceneObject != false || ! gameObject || gameObject . scene . handle == SceneOriginHandle )
33203349 {
3350+ // If this NetworkObject did register for SceneMigrationSynchronization and scene management is enabled and the gameObject is null,
3351+ if ( SceneMigrationSynchronization && NetworkManager . NetworkConfig . EnableSceneManagement && ! gameObject )
3352+ {
3353+ // then mark this instance to be removed from the scene migration synchronization list.
3354+ CleanUpDisposedObjects . Add ( NetworkObjectId ) ;
3355+ }
33213356 return ;
33223357 }
33233358
0 commit comments