Skip to content

Commit a725f59

Browse files
fix
Fixing the issue where destroy with scene could cause errors on non-authority instances.
1 parent 13abd46 commit a725f59

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,6 +1717,14 @@ private void OnDestroy()
17171717
// Authority is the server (client-server) and the owner or DAHost (distributed authority) when destroying a NetworkObject
17181718
var isAuthority = HasAuthority || NetworkManager.DAHost;
17191719

1720+
// If we are not the authority, check to see if this is one of the edge case scenarios where a NetworkObject could be getting
1721+
// destroyed due to unloading a scene or loading a scene in single mode.
1722+
if (!isAuthority && IsSpawned && NetworkManager.DistributedAuthorityMode && NetworkManager.NetworkConfig.EnableSceneManagement
1723+
&& NetworkManager.SceneManager.ShouldObjectBeDestroyedWhenUnloaded(this))
1724+
{
1725+
isAuthority = true;
1726+
}
1727+
17201728
if (NetworkManager.IsListening && !isAuthority && IsSpawned &&
17211729
(IsSceneObject == null || (IsSceneObject.Value != true)))
17221730
{
@@ -1727,6 +1735,7 @@ private void OnDestroy()
17271735
// if this happens. Instead, we should just generate a network log error and exit early (as long as we are not shutting down).
17281736
if (!NetworkManager.ShutdownInProgress)
17291737
{
1738+
17301739
// Since we still have a session connection, log locally and on the server to inform user of this issue.
17311740
if (NetworkManager.LogLevel <= LogLevel.Error)
17321741
{

com.unity.netcode.gameobjects/Runtime/SceneManagement/NetworkSceneManager.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Codice.CM.Common.Tree.Partial;
12
using System;
23
using System.Collections.Generic;
34
using System.Linq;
@@ -2823,6 +2824,44 @@ internal bool IsSceneEventInProgress()
28232824
return false;
28242825
}
28252826

2827+
/// <summary>
2828+
/// Used to determine if it is valid for a distributed authority client to destroy a spawned object
2829+
/// based on any current scene event in progress and/or the GameObject's scene status.
2830+
/// <see cref="NetworkObject.OnDestroy"/>
2831+
/// </summary>
2832+
/// <param name="networkObject">the NetworkObject to check</param>
2833+
internal bool ShouldObjectBeDestroyedWhenUnloaded(NetworkObject networkObject)
2834+
{
2835+
if (!IsSceneEventInProgress())
2836+
{
2837+
return false;
2838+
}
2839+
if (!networkObject.gameObject.scene.isLoaded)
2840+
{
2841+
return networkObject.DestroyWithScene;
2842+
}
2843+
var objectScene = networkObject.gameObject.scene;
2844+
var objectSceneHash = SceneHashFromNameOrPath(objectScene.name);
2845+
foreach (var sceneEventEntry in SceneEventProgressTracking)
2846+
{
2847+
if (sceneEventEntry.Value.HasTimedOut())
2848+
{
2849+
continue;
2850+
}
2851+
if (sceneEventEntry.Value.SceneEventType == SceneEventType.Unload && sceneEventEntry.Value.Status == SceneEventProgressStatus.Started
2852+
&& sceneEventEntry.Value.SceneHash == objectSceneHash)
2853+
{
2854+
return networkObject.DestroyWithScene;
2855+
}
2856+
if (sceneEventEntry.Value.SceneEventType == SceneEventType.Load && sceneEventEntry.Value.LoadSceneMode == LoadSceneMode.Single &&
2857+
sceneEventEntry.Value.SceneHash != objectSceneHash)
2858+
{
2859+
return networkObject.DestroyWithScene;
2860+
}
2861+
}
2862+
return false;
2863+
}
2864+
28262865
/// <summary>
28272866
/// Handles notifying clients when a NetworkObject has been migrated into a new scene
28282867
/// </summary>

0 commit comments

Comments
 (0)