11using System . Linq ;
2+ using System . Runtime . CompilerServices ;
23
34namespace 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,87 @@ 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 )
133- {
134- if ( clientId == networkManager . LocalClientId || clientId == ownerClientId )
135- {
136- continue ;
137- }
138- networkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , clientId ) ;
139- }
117+ return ;
140118 }
141119
142- // If we are deferring the despawn, then add it to the deferred despawn queue
143120 if ( networkManager . DistributedAuthorityMode )
144121 {
145- if ( DeferredDespawnTick > 0 )
122+ // If we are deferring the despawn, then add it to the deferred despawn queue
123+ // If DAHost has reached this point, it is not valid to add to the queue
124+ if ( DeferredDespawnTick > 0 && ! networkManager . DAHost )
146125 {
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- }
126+ HandleDeferredDespawn ( ref networkManager , ref networkObject ) ;
127+ return ;
156128 }
157129
158130 // 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 )
131+ if ( IsTargetedDestroy && TargetClientId != networkManager . LocalClientId )
160132 {
161133 networkObject . Observers . Remove ( TargetClientId ) ;
162134 return ;
163135 }
164136 }
165137
166- if ( networkObject != null )
138+ // Otherwise just despawn the NetworkObject right now
139+ networkManager . SpawnManager . OnDespawnNonAuthorityObject ( networkObject ) ;
140+ networkManager . NetworkMetrics . TrackObjectDestroyReceived ( context . SenderId , networkObject , context . MessageSize ) ;
141+ }
142+
143+ /// <summary>
144+ /// Handles forwarding the <see cref="DestroyObjectMessage"/> when acting as the DA Host
145+ /// </summary>
146+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
147+ private void HandleDAHostForwardMessage ( ulong senderId , ref NetworkManager networkManager , NetworkObject networkObject )
148+ {
149+ var message = new DestroyObjectMessage
167150 {
168- // Otherwise just despawn the NetworkObject right now
169- networkManager . SpawnManager . OnDespawnObject ( networkObject , DestroyGameObject ) ;
170- networkManager . NetworkMetrics . TrackObjectDestroyReceived ( context . SenderId , networkObject , context . MessageSize ) ;
151+ NetworkObjectId = NetworkObjectId ,
152+ DestroyGameObject = DestroyGameObject ,
153+ IsDistributedAuthority = true ,
154+ IsTargetedDestroy = IsTargetedDestroy ,
155+ TargetClientId = TargetClientId , // Just always populate this value whether we write it or not
156+ DeferredDespawnTick = DeferredDespawnTick ,
157+ } ;
158+ var ownerClientId = networkObject == null ? senderId : networkObject . OwnerClientId ;
159+ var clientIds = networkObject == null ? networkManager . ConnectedClientsIds . ToList ( ) : networkObject . Observers . ToList ( ) ;
160+
161+ foreach ( var clientId in clientIds )
162+ {
163+ if ( clientId != networkManager . LocalClientId && clientId != ownerClientId )
164+ {
165+ networkManager . ConnectionManager . SendMessage ( ref message , NetworkDelivery . ReliableSequenced , clientId ) ;
166+ }
171167 }
172168 }
169+
170+ /// <summary>
171+ /// Handles adding to the deferred despawn queue when the <see cref="DestroyObjectMessage"/> indicates a deferred despawn
172+ /// </summary>
173+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
174+ private void HandleDeferredDespawn ( ref NetworkManager networkManager , ref NetworkObject networkObject )
175+ {
176+ networkObject . DeferredDespawnTick = DeferredDespawnTick ;
177+ var hasCallback = networkObject . OnDeferredDespawnComplete != null ;
178+ networkManager . SpawnManager . DeferDespawnNetworkObject ( NetworkObjectId , DeferredDespawnTick , hasCallback ) ;
179+ }
173180 }
181+
174182}
0 commit comments