Skip to content

Commit 2456a82

Browse files
committed
Merge branch 'develop-2.0.0' of https://github.com/Unity-Technologies/com.unity.netcode.gameobjects into fix/mttb-959-exception-with-disabled-gameobjects
2 parents bd79f9b + 6a4f718 commit 2456a82

File tree

10 files changed

+167
-13
lines changed

10 files changed

+167
-13
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This workflow is for validating the Renovate configuration and docker image
2+
# updates for it.
3+
name: Renovate Validation
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
log-level:
8+
type: choice
9+
description: Select log level for Renovate
10+
options:
11+
- trace
12+
- debug
13+
- info
14+
- warn
15+
- error
16+
default: info
17+
required: false
18+
pull_request:
19+
paths:
20+
# we trigger validation on any changes to the renovate workflow files
21+
- .github/workflows/renovate*.yml
22+
# as well as for any possible location for the renovate config file
23+
- .github/renovate.json?
24+
25+
26+
jobs:
27+
renovate-validation:
28+
# The reusable workflow will be updated by renovate if there's a new version
29+
uses: Unity-Technologies/renovate-workflows/.github/workflows/[email protected]
30+
with:
31+
# This is the image that contains our custom renovate and will be auto
32+
# updated by Renovate itself.
33+
image: europe-docker.pkg.dev/unity-cds-services-prd/ds-docker/renovate:10.1.3@sha256:fdeed7bb524bd67611eb91ee1a5e990c8c73ed62c84a0cd5ef66c87eb5fd0d70
34+
dry-run: full
35+
log-level: ${{ github.event.inputs.log-level }}
36+
secrets:
37+
renovate-auth-secret: ${{ secrets.RENOVATE_AUTH_SECRET }}
38+
github-com-token: ${{ secrets.GH_COM_TOKEN }}

.github/workflows/renovate.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# This workflow runs Renovate against the current repo and will create PRs with outdated dependencies.
2+
name: Renovate
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
log-level:
8+
type: choice
9+
description: Select log level for Renovate
10+
options:
11+
- trace
12+
- debug
13+
- info
14+
- warn
15+
- error
16+
default: info
17+
required: false
18+
schedule:
19+
# Every 6 hours at the 6th minute.
20+
- cron: '06 */6 * * *'
21+
22+
jobs:
23+
renovate:
24+
# The reusable workflow will be updated by renovate if there's a new version
25+
uses: Unity-Technologies/renovate-workflows/.github/workflows/[email protected]
26+
with:
27+
# This is the image that contains our custom renovate and will be auto
28+
# updated by Renovate itself.
29+
image: europe-docker.pkg.dev/unity-cds-services-prd/ds-docker/renovate:10.1.3@sha256:fdeed7bb524bd67611eb91ee1a5e990c8c73ed62c84a0cd5ef66c87eb5fd0d70
30+
log-level: ${{ github.event.inputs.log-level }}
31+
secrets:
32+
renovate-auth-secret: ${{ secrets.RENOVATE_AUTH_SECRET }}
33+
github-com-token: ${{ secrets.GH_COM_TOKEN }}

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1313
### Fixed
1414

1515
- Fixed exception being thrown when a `GameObject` with an associated `NetworkTransform` is disabled. (#3243)
16+
- Fixed `NetworkObject.DeferDespawn` to respect the `DestroyGameObject` parameter. (#3219)
1617
- Changed the `NetworkTimeSystem.Sync` method to use half RTT to calculate the desired local time offset as opposed to the full RTT. (#3212)
1718
- Fixed issue where a spawned `NetworkObject` that was registered with a prefab handler and owned by a client would invoke destroy more than once on the host-server side if the client disconnected while the `NetworkObject` was still spawned. (#3200)
1819
- Fixed issue where `NetworkVariableBase` derived classes were not being re-initialized if the associated `NetworkObject` instance was not destroyed and re-spawned. (#3181)

com.unity.netcode.gameobjects/Runtime/Messaging/Messages/DestroyObjectMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public void Handle(ref NetworkContext context)
150150
{
151151
networkObject.DeferredDespawnTick = DeferredDespawnTick;
152152
var hasCallback = networkObject.OnDeferredDespawnComplete != null;
153-
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback);
153+
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback, DestroyGameObject);
154154
return;
155155
}
156156
}

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,7 @@ internal void ServerSpawnSceneObjectsOnStartSweep()
14501450
}
14511451

14521452
// Since we are spawing in-scene placed NetworkObjects for already loaded scenes,
1453-
// we need to add any in-scene placed NetworkObject to our tracking table
1453+
// we need to add any in-scene placed NetworkObject to our tracking table
14541454
var clearFirst = true;
14551455
foreach (var sceneLoaded in NetworkManager.SceneManager.ScenesLoaded)
14561456
{
@@ -1588,6 +1588,7 @@ internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObjec
15881588
{
15891589
NetworkObjectId = networkObject.NetworkObjectId,
15901590
DeferredDespawnTick = networkObject.DeferredDespawnTick,
1591+
// DANGO-TODO: Reconfigure Client-side object destruction on despawn
15911592
DestroyGameObject = networkObject.IsSceneObject != false ? destroyGameObject : true,
15921593
IsTargetedDestroy = false,
15931594
IsDistributedAuthority = distributedAuthority,
@@ -1601,6 +1602,7 @@ internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObjec
16011602
}
16021603

16031604
networkObject.IsSpawned = false;
1605+
networkObject.DeferredDespawnTick = 0;
16041606

16051607
if (SpawnedObjects.Remove(networkObject.NetworkObjectId))
16061608
{
@@ -1920,6 +1922,7 @@ internal struct DeferredDespawnObject
19201922
{
19211923
public int TickToDespawn;
19221924
public bool HasDeferredDespawnCheck;
1925+
public bool DestroyGameObject;
19231926
public ulong NetworkObjectId;
19241927
}
19251928

@@ -1931,12 +1934,13 @@ internal struct DeferredDespawnObject
19311934
/// <param name="networkObjectId">associated NetworkObject</param>
19321935
/// <param name="tickToDespawn">when to despawn the NetworkObject</param>
19331936
/// <param name="hasDeferredDespawnCheck">if true, user script is to be invoked to determine when to despawn</param>
1934-
internal void DeferDespawnNetworkObject(ulong networkObjectId, int tickToDespawn, bool hasDeferredDespawnCheck)
1937+
internal void DeferDespawnNetworkObject(ulong networkObjectId, int tickToDespawn, bool hasDeferredDespawnCheck, bool destroyGameObject)
19351938
{
19361939
var deferredDespawnObject = new DeferredDespawnObject()
19371940
{
19381941
TickToDespawn = tickToDespawn,
19391942
HasDeferredDespawnCheck = hasDeferredDespawnCheck,
1943+
DestroyGameObject = destroyGameObject,
19401944
NetworkObjectId = networkObjectId,
19411945
};
19421946
DeferredDespawnObjects.Add(deferredDespawnObject);
@@ -2001,7 +2005,7 @@ internal void DeferredDespawnUpdate(NetworkTime serverTime)
20012005
}
20022006
var networkObject = SpawnedObjects[deferredObjectEntry.NetworkObjectId];
20032007
// Local instance despawns the instance
2004-
OnDespawnObject(networkObject, true);
2008+
OnDespawnObject(networkObject, deferredObjectEntry.DestroyGameObject);
20052009
DeferredDespawnObjects.Remove(deferredObjectEntry);
20062010
}
20072011
}

com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,13 @@ public override void DisconnectLocalClient()
12201220
/// <param name="clientId">The client to disconnect</param>
12211221
public override void DisconnectRemoteClient(ulong clientId)
12221222
{
1223-
Debug.Assert(m_State == State.Listening, "DisconnectRemoteClient should be called on a listening server");
1223+
#if DEBUG
1224+
if (m_State != State.Listening)
1225+
{
1226+
Debug.LogWarning($"{nameof(DisconnectRemoteClient)} should only be called on a listening server!");
1227+
return;
1228+
}
1229+
#endif
12241230

12251231
if (m_State == State.Listening)
12261232
{
@@ -1292,7 +1298,13 @@ public NetworkEndpoint GetEndpoint(ulong clientId)
12921298
/// <param name="networkManager">The NetworkManager that initialized and owns the transport</param>
12931299
public override void Initialize(NetworkManager networkManager = null)
12941300
{
1295-
Debug.Assert(sizeof(ulong) == UnsafeUtility.SizeOf<NetworkConnection>(), "Netcode connection id size does not match UTP connection id size");
1301+
#if DEBUG
1302+
if (sizeof(ulong) != UnsafeUtility.SizeOf<NetworkConnection>())
1303+
{
1304+
Debug.LogWarning($"Netcode connection id size {sizeof(ulong)} does not match UTP connection id size {UnsafeUtility.SizeOf<NetworkConnection>()}!");
1305+
return;
1306+
}
1307+
#endif
12961308

12971309
m_NetworkManager = networkManager;
12981310

com.unity.netcode.gameobjects/TestHelpers/Runtime/NetcodeIntegrationTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,9 @@ protected void ShutdownAndCleanUp()
11561156
// reset the m_ServerWaitForTick for the next test to initialize
11571157
s_DefaultWaitForTick = new WaitForSecondsRealtime(1.0f / k_DefaultTickRate);
11581158
VerboseDebug($"Exiting {nameof(ShutdownAndCleanUp)}");
1159+
1160+
// Assure any remaining NetworkManagers are destroyed
1161+
DestroyNetworkManagers();
11591162
}
11601163

11611164
protected IEnumerator CoroutineShutdownAndCleanUp()
@@ -1195,6 +1198,9 @@ protected IEnumerator CoroutineShutdownAndCleanUp()
11951198
// reset the m_ServerWaitForTick for the next test to initialize
11961199
s_DefaultWaitForTick = new WaitForSecondsRealtime(1.0f / k_DefaultTickRate);
11971200
VerboseDebug($"Exiting {nameof(ShutdownAndCleanUp)}");
1201+
1202+
// Assure any remaining NetworkManagers are destroyed
1203+
DestroyNetworkManagers();
11981204
}
11991205

12001206
/// <summary>
@@ -1244,6 +1250,19 @@ public IEnumerator TearDown()
12441250
VerboseDebug($"Exiting {nameof(TearDown)}");
12451251
LogWaitForMessages();
12461252
NetcodeLogAssert.Dispose();
1253+
1254+
}
1255+
1256+
/// <summary>
1257+
/// Destroys any remaining NetworkManager instances
1258+
/// </summary>
1259+
private void DestroyNetworkManagers()
1260+
{
1261+
var networkManagers = Object.FindObjectsByType<NetworkManager>(FindObjectsSortMode.None);
1262+
foreach (var networkManager in networkManagers)
1263+
{
1264+
Object.DestroyImmediate(networkManager.gameObject);
1265+
}
12471266
}
12481267

12491268
/// <summary>

com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/DeferredDespawningTests.cs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,25 @@
99

1010
namespace Unity.Netcode.RuntimeTests
1111
{
12+
[TestFixture(SetDestroyGameObject.DestroyGameObject)]
13+
[TestFixture(SetDestroyGameObject.DontDestroyGameObject)]
1214
internal class DeferredDespawningTests : IntegrationTestWithApproximation
1315
{
1416
private const int k_DaisyChainedCount = 5;
1517
protected override int NumberOfClients => 2;
1618
private List<GameObject> m_DaisyChainedDespawnObjects = new List<GameObject>();
1719
private List<ulong> m_HasReachedEnd = new List<ulong>();
1820

19-
public DeferredDespawningTests() : base(HostOrServer.DAHost)
21+
public enum SetDestroyGameObject
2022
{
23+
DestroyGameObject,
24+
DontDestroyGameObject,
25+
}
26+
private bool m_DestroyGameObject;
27+
28+
public DeferredDespawningTests(SetDestroyGameObject destroyGameObject) : base(HostOrServer.DAHost)
29+
{
30+
m_DestroyGameObject = destroyGameObject == SetDestroyGameObject.DestroyGameObject;
2131
}
2232

2333
protected override void OnServerAndClientsCreated()
@@ -45,12 +55,28 @@ protected override void OnServerAndClientsCreated()
4555
[UnityTest]
4656
public IEnumerator DeferredDespawning()
4757
{
58+
// Setup for test
59+
DeferredDespawnDaisyChained.DestroyGameObject = m_DestroyGameObject;
4860
DeferredDespawnDaisyChained.EnableVerbose = m_EnableVerboseDebug;
61+
DeferredDespawnDaisyChained.ClientRelativeInstances = new Dictionary<ulong, Dictionary<ulong, DeferredDespawnDaisyChained>>();
62+
63+
// Spawn the initial object
4964
var rootInstance = SpawnObject(m_DaisyChainedDespawnObjects[0], m_ServerNetworkManager);
5065
DeferredDespawnDaisyChained.ReachedLastChainInstance = ReachedLastChainObject;
66+
67+
// Wait for the chain of objects to spawn and despawn
5168
var timeoutHelper = new TimeoutHelper(300);
5269
yield return WaitForConditionOrTimeOut(HaveAllClientsReachedEndOfChain, timeoutHelper);
5370
AssertOnTimeout($"Timed out waiting for all children to reach the end of their chained deferred despawns!", timeoutHelper);
71+
72+
if (m_DestroyGameObject)
73+
{
74+
Assert.IsTrue(rootInstance == null); // Assert.IsNull doesn't work here
75+
}
76+
else
77+
{
78+
Assert.IsTrue(rootInstance != null); // Assert.IsNotNull doesn't work here
79+
}
5480
}
5581

5682
private bool HaveAllClientsReachedEndOfChain()
@@ -88,9 +114,10 @@ private void ReachedLastChainObject(ulong clientId)
88114
internal class DeferredDespawnDaisyChained : NetworkBehaviour
89115
{
90116
public static bool EnableVerbose;
117+
public static bool DestroyGameObject;
91118
public static Action<ulong> ReachedLastChainInstance;
92119
private const int k_StartingDeferTick = 4;
93-
public static Dictionary<ulong, Dictionary<ulong, DeferredDespawnDaisyChained>> ClientRelativeInstances = new Dictionary<ulong, Dictionary<ulong, DeferredDespawnDaisyChained>>();
120+
public static Dictionary<ulong, Dictionary<ulong, DeferredDespawnDaisyChained>> ClientRelativeInstances;
94121
public bool IsRoot;
95122
public GameObject PrefabToSpawnWhenDespawned;
96123
public bool WasContactedByPeviousChainMember { get; private set; }
@@ -182,7 +209,7 @@ private void InvokeDespawn()
182209
{
183210
FailTest($"[{nameof(InvokeDespawn)}] Client is not the authority but this was invoked (integration test logic issue)!");
184211
}
185-
NetworkObject.DeferDespawn(DeferDespawnTick);
212+
NetworkObject.DeferDespawn(DeferDespawnTick, DestroyGameObject);
186213
}
187214

188215
public override void OnDeferringDespawn(int despawnTick)
@@ -241,7 +268,7 @@ private void Update()
241268
continue;
242269
}
243270

244-
// This should happen shortly afte the instances spawns (based on the deferred despawn count)
271+
// This should happen shortly after the instances spawn (based on the deferred despawn count)
245272
if (!IsRoot && !ClientRelativeInstances[clientId][NetworkObjectId].WasContactedByPeviousChainMember)
246273
{
247274
// exit early if the non-authority instance has not been contacted yet

com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ public IEnumerator DoesNotActAfterShutdown([Values] AfterShutdownAction afterShu
531531
{
532532
m_Server.DisconnectRemoteClient(m_Client1.ServerClientId);
533533

534-
LogAssert.Expect(LogType.Assert, "DisconnectRemoteClient should be called on a listening server");
534+
LogAssert.Expect(LogType.Warning, $"{nameof(UnityTransport.DisconnectRemoteClient)} should only be called on a listening server!");
535535
}
536536
else if (afterShutdownAction == AfterShutdownAction.DisconnectLocalClient)
537537
{

testproject/Assets/Tests/Runtime/NetworkSceneManager/InScenePlacedNetworkObjectTests.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ protected override bool CanStartServerAndClients()
5353
return m_CanStartServerAndClients;
5454
}
5555

56+
public enum DespawnMode
57+
{
58+
Despawn,
59+
DeferDespawn,
60+
}
61+
5662
/// <summary>
5763
/// This verifies that in-scene placed NetworkObjects will be properly
5864
/// synchronized if:
@@ -61,8 +67,13 @@ protected override bool CanStartServerAndClients()
6167
/// NetworkObject as a NetworkPrefab
6268
/// </summary>
6369
[UnityTest]
64-
public IEnumerator InSceneNetworkObjectSynchAndSpawn()
70+
public IEnumerator InSceneNetworkObjectSynchAndSpawn([Values] DespawnMode despawnMode)
6571
{
72+
if (!m_DistributedAuthority && despawnMode == DespawnMode.DeferDespawn)
73+
{
74+
Assert.Ignore($"Test ignored as DeferDespawn is only valid with Distributed Authority mode.");
75+
}
76+
6677
NetworkObjectTestComponent.VerboseDebug = true;
6778
// Because despawning a client will cause it to shutdown and clean everything in the
6879
// scene hierarchy, we have to prevent one of the clients from spawning initially before
@@ -99,7 +110,16 @@ public IEnumerator InSceneNetworkObjectSynchAndSpawn()
99110

100111
// Despawn the in-scene placed NetworkObject
101112
Debug.Log("Despawning In-Scene placed NetworkObject");
102-
serverObject.Despawn(false);
113+
114+
if (despawnMode == DespawnMode.Despawn)
115+
{
116+
serverObject.Despawn(false);
117+
}
118+
else
119+
{
120+
serverObject.DeferDespawn(1, false);
121+
}
122+
103123
yield return WaitForConditionOrTimeOut(() => NetworkObjectTestComponent.SpawnedInstances.Count == 0);
104124
AssertOnTimeout($"Timed out waiting for all in-scene instances to be despawned! Current spawned count: {NetworkObjectTestComponent.SpawnedInstances.Count()}");
105125

0 commit comments

Comments
 (0)