Skip to content

Commit 7c06255

Browse files
Merge branch 'develop-2.0.0' into PVP-151-fix
2 parents ce10cff + 711aa02 commit 7c06255

File tree

9 files changed

+116
-105
lines changed

9 files changed

+116
-105
lines changed

.github/CODEOWNERS

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22
# Order is important; the last matching pattern takes the most precedence.
33

44
* @Unity-Technologies/multiplayer-sdk
5-
Profiling/ @Unity-Technologies/multiplayer-tools
6-
Metrics/ @Unity-Technologies/multiplayer-tools
7-
/com.unity.netcode.gameobjects/Runtime/Transports/ @Unity-Technologies/multiplayer-workflows
8-
/com.unity.netcode.gameobjects/Tests/Editor/Transports/ @Unity-Technologies/multiplayer-workflows
9-
/com.unity.netcode.gameobjects/Tests/Runtime/Transports/ @Unity-Technologies/multiplayer-workflows
10-
*.asmdef @chrispope @miniwolf
11-
package.json @chrispope @miniwolf
12-
AssemblyInfo.cs @chrispope @miniwolf
13-
.editorconfig @chrispope @miniwolf
14-
.gitignore @chrispope @miniwolf
15-
.github/ @chrispope @miniwolf
16-
.yamato/ @chrispope @miniwolf
5+
*.asmdef @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM
6+
package.json @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM
7+
AssemblyInfo.cs @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM
8+
.editorconfig @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM
9+
.gitignore @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM
10+
.github/ @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM
11+
.yamato/ @miniwolf @NoelStephensUnity @fluong6 @michalChrobot @EmandM

.github/renovate.json5

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,19 @@
77
"local>Unity-Technologies/unity-renovate-config"
88
],
99
"prConcurrentLimit": 100,
10-
// Ignore commits produced by github actions workflows
10+
// Ignore commits produced by GitHub actions workflows
1111
"gitIgnoredAuthors": ["githubaction@githubaction.com"],
1212
"ignorePaths": [
1313
"**/node_modules/**",
1414
// Don't renovate files in special folders using ~ as suffix
15-
"**/*~/**"
15+
"**/*~/**",
16+
"com.unity.netcode.gameobjects/**/*",
17+
"Examples/**/*",
18+
"testproject/**/*",
19+
"minimalproject/**/*",
20+
"testproject-tools-integration/**/*"
1621
],
1722
"packageRules": [
18-
1923
// Run unity-upm-project and unity-upm-package only on weekends to reduce PR noise
2024
// Also ensure dependencies won't be downgraded when they don't exist in the public repositories
2125
{
@@ -27,13 +31,7 @@
2731
"schedule": [
2832
"every weekend"
2933
],
30-
"rollbackPrs": false
31-
},
32-
33-
// Enable automerge for Bokken image updates
34-
{
35-
"matchDatasources": ["unity-bokken"],
36-
"automerge": false,
37-
},
34+
"rollbackPrs": false,
35+
}
3836
],
3937
}

.github/workflows/conventional-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
steps:
1919
- name: semantic-pull-request
2020
# Internal Unity mirror available at jesseo/action-semantic-pull-request, but actions from private repos aren't supported, so continue to use the public one below
21-
uses: amannn/action-semantic-pull-request@b7a9a97cb10fa6e1ae02647e718798175f6b1f1d
21+
uses: amannn/action-semantic-pull-request@40166f00814508ec3201fc8595b393d451c8cd80
2222
env:
2323
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2424
with:

Tools/CI/global.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

com.unity.netcode.gameobjects/CHANGELOG.md

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

1313
### Fixed
1414

15+
- Fixed DestroyObject flow on non-authority game clients. (#3291)
1516
- Fixed exception being thrown when a `GameObject` with an associated `NetworkTransform` is disabled. (#3243)
1617
- Fixed issue where the scene migration synchronization table was not cleaned up if the `GameObject` of a `NetworkObject` is destroyed before it should have been. (#3230)
1718
- Fixed issue where the scene migration synchronization table was not cleaned up upon `NetworkManager` shutting down. (#3230)

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

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Linq;
2+
using System.Runtime.CompilerServices;
23

34
namespace Unity.Netcode
45
{
@@ -81,7 +82,7 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
8182

8283
reader.ReadValueSafe(out DestroyGameObject);
8384

84-
if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject))
85+
if (!networkManager.SpawnManager.SpawnedObjects.ContainsKey(NetworkObjectId))
8586
{
8687
// Client-Server mode we always defer where in distributed authority mode we only defer if it is not a targeted destroy
8788
if (!networkManager.DistributedAuthorityMode || (networkManager.DistributedAuthorityMode && !IsTargetedDestroy))
@@ -95,80 +96,90 @@ public bool Deserialize(FastBufferReader reader, ref NetworkContext context, int
9596
public void Handle(ref NetworkContext context)
9697
{
9798
var networkManager = (NetworkManager)context.SystemOwner;
99+
networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out var networkObject);
98100

99-
var networkObject = (NetworkObject)null;
100-
if (!networkManager.DistributedAuthorityMode)
101+
// The DAHost needs to forward despawn messages to the other clients
102+
if (networkManager.DAHost)
101103
{
102-
// If this NetworkObject does not exist on this instance then exit early
103-
if (!networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out networkObject))
104-
{
105-
return;
106-
}
107-
}
108-
else
109-
{
110-
networkManager.SpawnManager.SpawnedObjects.TryGetValue(NetworkObjectId, out networkObject);
111-
if (!networkManager.DAHost && networkObject == null)
104+
HandleDAHostForwardMessage(context.SenderId, ref networkManager, networkObject);
105+
106+
// DAHost adds the object to the queue only if it is not a targeted destroy, or it is and the target is the DAHost client.
107+
if (networkObject && DeferredDespawnTick > 0 && (!IsTargetedDestroy || (IsTargetedDestroy && TargetClientId == 0)))
112108
{
113-
// If this NetworkObject does not exist on this instance then exit early
109+
HandleDeferredDespawn(ref networkManager, ref networkObject);
114110
return;
115111
}
116112
}
117-
// DANGO-TODO: This is just a quick way to foward despawn messages to the remaining clients
118-
if (networkManager.DistributedAuthorityMode && networkManager.DAHost)
113+
114+
// If this NetworkObject does not exist on this instance then exit early
115+
if (!networkObject)
119116
{
120-
var message = new DestroyObjectMessage
121-
{
122-
NetworkObjectId = NetworkObjectId,
123-
DestroyGameObject = DestroyGameObject,
124-
IsDistributedAuthority = true,
125-
IsTargetedDestroy = IsTargetedDestroy,
126-
TargetClientId = TargetClientId, // Just always populate this value whether we write it or not
127-
DeferredDespawnTick = DeferredDespawnTick,
128-
};
129-
var ownerClientId = networkObject == null ? context.SenderId : networkObject.OwnerClientId;
130-
var clientIds = networkObject == null ? networkManager.ConnectedClientsIds.ToList() : networkObject.Observers.ToList();
131-
132-
foreach (var clientId in clientIds)
117+
if (networkManager.LogLevel <= LogLevel.Developer)
133118
{
134-
if (clientId == networkManager.LocalClientId || clientId == ownerClientId)
135-
{
136-
continue;
137-
}
138-
networkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, clientId);
119+
NetworkLog.LogWarning($"[{nameof(DestroyObjectMessage)}] Received destroy object message for NetworkObjectId ({NetworkObjectId}) on Client-{networkManager.LocalClientId}, but that {nameof(NetworkObject)} does not exist!");
139120
}
121+
return;
140122
}
141123

142-
// If we are deferring the despawn, then add it to the deferred despawn queue
143124
if (networkManager.DistributedAuthorityMode)
144125
{
145-
if (DeferredDespawnTick > 0)
126+
// If we are deferring the despawn, then add it to the deferred despawn queue
127+
// If DAHost has reached this point, it is not valid to add to the queue
128+
if (DeferredDespawnTick > 0 && !networkManager.DAHost)
146129
{
147-
// Clients always add it to the queue while DAHost will only add it to the queue if it is not a targeted destroy or it is and the target is the
148-
// DAHost client.
149-
if (!networkManager.DAHost || (networkManager.DAHost && (!IsTargetedDestroy || (IsTargetedDestroy && TargetClientId == 0))))
150-
{
151-
networkObject.DeferredDespawnTick = DeferredDespawnTick;
152-
var hasCallback = networkObject.OnDeferredDespawnComplete != null;
153-
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback, DestroyGameObject);
154-
return;
155-
}
130+
HandleDeferredDespawn(ref networkManager, ref networkObject);
131+
return;
156132
}
157133

158134
// If this is targeted and we are not the target, then just update our local observers for this object
159-
if (IsTargetedDestroy && TargetClientId != networkManager.LocalClientId && networkObject != null)
135+
if (IsTargetedDestroy && TargetClientId != networkManager.LocalClientId)
160136
{
161137
networkObject.Observers.Remove(TargetClientId);
162138
return;
163139
}
164140
}
165141

166-
if (networkObject != null)
142+
// Otherwise just despawn the NetworkObject right now
143+
networkManager.SpawnManager.OnDespawnNonAuthorityObject(networkObject);
144+
networkManager.NetworkMetrics.TrackObjectDestroyReceived(context.SenderId, networkObject, context.MessageSize);
145+
}
146+
147+
/// <summary>
148+
/// Handles forwarding the <see cref="DestroyObjectMessage"/> when acting as the DA Host
149+
/// </summary>
150+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
151+
private void HandleDAHostForwardMessage(ulong senderId, ref NetworkManager networkManager, NetworkObject networkObject)
152+
{
153+
var message = new DestroyObjectMessage
167154
{
168-
// Otherwise just despawn the NetworkObject right now
169-
networkManager.SpawnManager.OnDespawnObject(networkObject, DestroyGameObject);
170-
networkManager.NetworkMetrics.TrackObjectDestroyReceived(context.SenderId, networkObject, context.MessageSize);
155+
NetworkObjectId = NetworkObjectId,
156+
DestroyGameObject = DestroyGameObject,
157+
IsDistributedAuthority = true,
158+
IsTargetedDestroy = IsTargetedDestroy,
159+
TargetClientId = TargetClientId, // Just always populate this value whether we write it or not
160+
DeferredDespawnTick = DeferredDespawnTick,
161+
};
162+
var ownerClientId = networkObject == null ? senderId : networkObject.OwnerClientId;
163+
var clientIds = networkObject == null ? networkManager.ConnectedClientsIds.ToList() : networkObject.Observers.ToList();
164+
165+
foreach (var clientId in clientIds)
166+
{
167+
if (clientId != networkManager.LocalClientId && clientId != ownerClientId)
168+
{
169+
networkManager.ConnectionManager.SendMessage(ref message, NetworkDelivery.ReliableSequenced, clientId);
170+
}
171171
}
172172
}
173+
174+
/// <summary>
175+
/// Handles adding to the deferred despawn queue when the <see cref="DestroyObjectMessage"/> indicates a deferred despawn
176+
/// </summary>
177+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
178+
private void HandleDeferredDespawn(ref NetworkManager networkManager, ref NetworkObject networkObject)
179+
{
180+
networkObject.DeferredDespawnTick = DeferredDespawnTick;
181+
var hasCallback = networkObject.OnDeferredDespawnComplete != null;
182+
networkManager.SpawnManager.DeferDespawnNetworkObject(NetworkObjectId, DeferredDespawnTick, hasCallback);
183+
}
173184
}
174185
}

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

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics.CodeAnalysis;
34
using System.Linq;
45
using System.Text;
56
using UnityEngine;
@@ -1470,7 +1471,6 @@ internal void ServerSpawnSceneObjectsOnStartSweep()
14701471
#else
14711472
var networkObjects = UnityEngine.Object.FindObjectsOfType<NetworkObject>();
14721473
#endif
1473-
var isConnectedCMBService = NetworkManager.CMBServiceConnection;
14741474
var networkObjectsToSpawn = new List<NetworkObject>();
14751475
for (int i = 0; i < networkObjects.Length; i++)
14761476
{
@@ -1510,15 +1510,30 @@ internal void ServerSpawnSceneObjectsOnStartSweep()
15101510
networkObjectsToSpawn.Clear();
15111511
}
15121512

1513+
/// <summary>
1514+
/// Called when destroying an object after receiving a <see cref="DestroyObjectMessage"/>.
1515+
/// Processes logic for how to destroy objects on the non-authority client.
1516+
/// </summary>
1517+
internal void OnDespawnNonAuthorityObject([NotNull] NetworkObject networkObject)
1518+
{
1519+
if (networkObject.HasAuthority)
1520+
{
1521+
NetworkLog.LogError($"OnDespawnNonAuthorityObject called on object {networkObject.NetworkObjectId} when is current client {NetworkManager.LocalClientId} has authority on this object.");
1522+
}
1523+
1524+
// On the non-authority, never destroy the game object when InScenePlaced, otherwise always destroy on non-authority side
1525+
OnDespawnObject(networkObject, networkObject.IsSceneObject == false);
1526+
}
1527+
15131528
internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObject, bool modeDestroy = false)
15141529
{
1515-
if (NetworkManager == null)
1530+
if (!NetworkManager)
15161531
{
15171532
return;
15181533
}
15191534

15201535
// We have to do this check first as subsequent checks assume we can access NetworkObjectId.
1521-
if (networkObject == null)
1536+
if (!networkObject)
15221537
{
15231538
Debug.LogWarning($"Trying to destroy network object but it is null");
15241539
return;
@@ -1632,8 +1647,7 @@ internal void OnDespawnObject(NetworkObject networkObject, bool destroyGameObjec
16321647
{
16331648
NetworkObjectId = networkObject.NetworkObjectId,
16341649
DeferredDespawnTick = networkObject.DeferredDespawnTick,
1635-
// DANGO-TODO: Reconfigure Client-side object destruction on despawn
1636-
DestroyGameObject = networkObject.IsSceneObject != false ? destroyGameObject : true,
1650+
DestroyGameObject = destroyGameObject,
16371651
IsTargetedDestroy = false,
16381652
IsDistributedAuthority = distributedAuthority,
16391653
};
@@ -2006,7 +2020,6 @@ internal struct DeferredDespawnObject
20062020
{
20072021
public int TickToDespawn;
20082022
public bool HasDeferredDespawnCheck;
2009-
public bool DestroyGameObject;
20102023
public ulong NetworkObjectId;
20112024
}
20122025

@@ -2018,13 +2031,12 @@ internal struct DeferredDespawnObject
20182031
/// <param name="networkObjectId">associated NetworkObject</param>
20192032
/// <param name="tickToDespawn">when to despawn the NetworkObject</param>
20202033
/// <param name="hasDeferredDespawnCheck">if true, user script is to be invoked to determine when to despawn</param>
2021-
internal void DeferDespawnNetworkObject(ulong networkObjectId, int tickToDespawn, bool hasDeferredDespawnCheck, bool destroyGameObject)
2034+
internal void DeferDespawnNetworkObject(ulong networkObjectId, int tickToDespawn, bool hasDeferredDespawnCheck)
20222035
{
20232036
var deferredDespawnObject = new DeferredDespawnObject()
20242037
{
20252038
TickToDespawn = tickToDespawn,
20262039
HasDeferredDespawnCheck = hasDeferredDespawnCheck,
2027-
DestroyGameObject = destroyGameObject,
20282040
NetworkObjectId = networkObjectId,
20292041
};
20302042
DeferredDespawnObjects.Add(deferredDespawnObject);
@@ -2041,15 +2053,21 @@ internal void DeferredDespawnUpdate(NetworkTime serverTime)
20412053
return;
20422054
}
20432055
var currentTick = serverTime.Tick;
2044-
var deferredCallbackCount = DeferredDespawnObjects.Count();
2045-
for (int i = 0; i < deferredCallbackCount; i++)
2056+
var deferredDespawnCount = DeferredDespawnObjects.Count;
2057+
// Loop forward and to process user callbacks and update despawn ticks
2058+
for (int i = 0; i < deferredDespawnCount; i++)
20462059
{
20472060
var deferredObjectEntry = DeferredDespawnObjects[i];
20482061
if (!deferredObjectEntry.HasDeferredDespawnCheck)
20492062
{
20502063
continue;
20512064
}
2052-
var networkObject = SpawnedObjects[deferredObjectEntry.NetworkObjectId];
2065+
2066+
if (!SpawnedObjects.TryGetValue(deferredObjectEntry.NetworkObjectId, out var networkObject))
2067+
{
2068+
continue;
2069+
}
2070+
20532071
// Double check to make sure user did not remove the callback
20542072
if (networkObject.OnDeferredDespawnComplete != null)
20552073
{
@@ -2074,23 +2092,21 @@ internal void DeferredDespawnUpdate(NetworkTime serverTime)
20742092
}
20752093

20762094
// Parse backwards so we can remove objects as we parse through them
2077-
for (int i = DeferredDespawnObjects.Count - 1; i >= 0; i--)
2095+
for (int i = deferredDespawnCount - 1; i >= 0; i--)
20782096
{
20792097
var deferredObjectEntry = DeferredDespawnObjects[i];
20802098
if (deferredObjectEntry.TickToDespawn >= currentTick)
20812099
{
20822100
continue;
20832101
}
20842102

2085-
if (!SpawnedObjects.ContainsKey(deferredObjectEntry.NetworkObjectId))
2103+
if (SpawnedObjects.TryGetValue(deferredObjectEntry.NetworkObjectId, out var networkObject))
20862104
{
2087-
DeferredDespawnObjects.Remove(deferredObjectEntry);
2088-
continue;
2105+
// Local instance despawns the instance
2106+
OnDespawnNonAuthorityObject(networkObject);
20892107
}
2090-
var networkObject = SpawnedObjects[deferredObjectEntry.NetworkObjectId];
2091-
// Local instance despawns the instance
2092-
OnDespawnObject(networkObject, deferredObjectEntry.DestroyGameObject);
2093-
DeferredDespawnObjects.Remove(deferredObjectEntry);
2108+
2109+
DeferredDespawnObjects.RemoveAt(i);
20942110
}
20952111
}
20962112

minimalproject/Packages/manifest.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
{
22
"dependencies": {
3-
"com.unity.ai.navigation": "2.0.5",
4-
"com.unity.multiplayer.center": "1.0.0",
5-
"com.unity.netcode.gameobjects": "file:../../com.unity.netcode.gameobjects",
6-
"com.unity.modules.accessibility": "1.0.0"
3+
"com.unity.netcode.gameobjects": "file:../../com.unity.netcode.gameobjects"
74
},
85
"testables": [
96
"com.unity.netcode.gameobjects"

testproject-tools-integration/Packages/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"com.unity.ai.navigation": "2.0.5",
55
"com.unity.ide.rider": "3.0.31",
66
"com.unity.multiplayer.center": "1.0.0",
7-
"com.unity.multiplayer.tools": "https://github.com/Unity-Technologies/com.unity.multiplayer.tools.git#release/1.1.0",
7+
"com.unity.multiplayer.tools": "2.2.3",
88
"com.unity.netcode.gameobjects": "file:../../com.unity.netcode.gameobjects",
99
"com.unity.test-framework": "1.4.6",
1010
"com.unity.test-framework.performance": "3.0.3",

0 commit comments

Comments
 (0)