Skip to content

Commit 5617951

Browse files
Merge branch 'develop-2.0.0' into NGO-CI-rewrite-for-develop-2.0.0
2 parents 6d76d90 + 6a4f718 commit 5617951

File tree

17 files changed

+723
-61
lines changed

17 files changed

+723
-61
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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ Additional documentation and release notes are available at [Multiplayer Documen
1212

1313
### Fixed
1414

15+
- Fixed `NetworkObject.DeferDespawn` to respect the `DestroyGameObject` parameter. (#3219)
16+
- Changed the `NetworkTimeSystem.Sync` method to use half RTT to calculate the desired local time offset as opposed to the full RTT. (#3212)
1517
- 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)
18+
- Fixed issue where `NetworkVariableBase` derived classes were not being re-initialized if the associated `NetworkObject` instance was not destroyed and re-spawned. (#3181)
1619

1720
### Changed
1821

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,13 @@ internal void InternalOnNetworkDespawn()
815815
{
816816
Debug.LogException(e);
817817
}
818+
819+
// Deinitialize all NetworkVariables in the event the associated
820+
// NetworkObject is recylced (in-scene placed or pooled).
821+
for (int i = 0; i < NetworkVariableFields.Count; i++)
822+
{
823+
NetworkVariableFields[i].Deinitialize();
824+
}
818825
}
819826

820827
/// <summary>
@@ -918,10 +925,30 @@ internal void __nameNetworkVariable(NetworkVariableBase variable, string varName
918925
variable.Name = varName;
919926
}
920927

928+
/// <summary>
929+
/// Does a first pass initialization for RPCs and NetworkVariables
930+
/// If already initialized, then it just re-initializes the NetworkVariables.
931+
/// </summary>
921932
internal void InitializeVariables()
922933
{
923934
if (m_VarInit)
924935
{
936+
// If the primary initialization has already been done, then go ahead
937+
// and re-initialize each NetworkVariable in the event it is an in-scene
938+
// placed NetworkObject in an already loaded scene that has already been
939+
// used within a network session =or= if this is a pooled NetworkObject
940+
// that is being repurposed.
941+
for (int i = 0; i < NetworkVariableFields.Count; i++)
942+
{
943+
// If already initialized, then skip
944+
if (NetworkVariableFields[i].HasBeenInitialized)
945+
{
946+
continue;
947+
}
948+
NetworkVariableFields[i].Initialize(this);
949+
}
950+
// Exit early as we don't need to run through the rest of this initialization
951+
// process
925952
return;
926953
}
927954

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ internal void SetSessionOwner(ulong sessionOwner)
225225
foreach (var networkObjectEntry in SpawnManager.SpawnedObjects)
226226
{
227227
var networkObject = networkObjectEntry.Value;
228-
if (networkObject.IsOwnershipSessionOwner && LocalClient.IsSessionOwner)
228+
if (networkObject.IsOwnershipSessionOwner && networkObject.OwnerClientId != LocalClientId)
229229
{
230230
SpawnManager.ChangeOwnership(networkObject, LocalClientId, true);
231231
}

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/NetworkVariable/NetworkVariableBase.cs

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public abstract class NetworkVariableBase : IDisposable
3535

3636
private NetworkManager m_InternalNetworkManager;
3737

38+
// Determines if this NetworkVariable has been "initialized" to prevent initializing more than once which can happen when first
39+
// instantiated and spawned. If this NetworkVariable instance is on an in-scene placed NetworkObject =or= a pooled NetworkObject
40+
// that can persist between sessions and/or be recycled we need to reset the LastUpdateSent value prior to spawning otherwise
41+
// this NetworkVariableBase property instance will not update until the last session time used.
42+
internal bool HasBeenInitialized { get; private set; }
43+
3844
internal string GetWritePermissionError()
3945
{
4046
return $"|Client-{m_NetworkManager.LocalClientId}|{m_NetworkBehaviour.name}|{Name}| Write permissions ({WritePerm}) for this client instance is not allowed!";
@@ -45,17 +51,7 @@ internal void LogWritePermissionError()
4551
Debug.LogError(GetWritePermissionError());
4652
}
4753

48-
private protected NetworkManager m_NetworkManager
49-
{
50-
get
51-
{
52-
if (m_InternalNetworkManager == null && m_NetworkBehaviour && m_NetworkBehaviour.NetworkObject?.NetworkManager)
53-
{
54-
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject?.NetworkManager;
55-
}
56-
return m_InternalNetworkManager;
57-
}
58-
}
54+
private protected NetworkManager m_NetworkManager => m_InternalNetworkManager;
5955

6056
public NetworkBehaviour GetBehaviour()
6157
{
@@ -68,21 +64,77 @@ public NetworkBehaviour GetBehaviour()
6864
/// <param name="networkBehaviour">The NetworkBehaviour the NetworkVariable belongs to</param>
6965
public void Initialize(NetworkBehaviour networkBehaviour)
7066
{
71-
m_InternalNetworkManager = null;
67+
// If we have already been initialized, then exit early.
68+
// This can happen on the very first instantiation and spawning of the associated NetworkObject
69+
if (HasBeenInitialized)
70+
{
71+
return;
72+
}
73+
74+
// Throw an exception if there is an invalid NetworkBehaviour parameter
75+
if (!networkBehaviour)
76+
{
77+
throw new Exception($"[{GetType().Name}][Initialize] {nameof(NetworkBehaviour)} parameter passed in is null!");
78+
}
7279
m_NetworkBehaviour = networkBehaviour;
73-
if (m_NetworkBehaviour && m_NetworkBehaviour.NetworkObject?.NetworkManager)
80+
81+
// Throw an exception if there is no NetworkManager available
82+
if (!m_NetworkBehaviour.NetworkManager)
7483
{
75-
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject?.NetworkManager;
76-
// When in distributed authority mode, there is no such thing as server write permissions
77-
InternalWritePerm = m_InternalNetworkManager.DistributedAuthorityMode ? NetworkVariableWritePermission.Owner : InternalWritePerm;
84+
// Exit early if there has yet to be a NetworkManager assigned.
85+
// This is ok because Initialize is invoked multiple times until
86+
// it is considered "initialized".
87+
return;
88+
}
7889

79-
if (m_NetworkBehaviour.NetworkManager.NetworkTimeSystem != null)
80-
{
81-
UpdateLastSentTime();
82-
}
90+
if (!m_NetworkBehaviour.NetworkObject)
91+
{
92+
// Exit early if there has yet to be a NetworkObject assigned.
93+
// This is ok because Initialize is invoked multiple times until
94+
// it is considered "initialized".
95+
return;
96+
}
97+
98+
if (!m_NetworkBehaviour.NetworkObject.NetworkManagerOwner)
99+
{
100+
// Exit early if there has yet to be a NetworkManagerOwner assigned
101+
// to the NetworkObject. This is ok because Initialize is invoked
102+
// multiple times until it is considered "initialized".
103+
return;
83104
}
105+
m_InternalNetworkManager = m_NetworkBehaviour.NetworkObject.NetworkManagerOwner;
106+
107+
// When in distributed authority mode, there is no such thing as server write permissions
108+
InternalWritePerm = m_InternalNetworkManager.DistributedAuthorityMode ? NetworkVariableWritePermission.Owner : InternalWritePerm;
84109

85110
OnInitialize();
111+
112+
// Some unit tests don't operate with a running NetworkManager.
113+
// Only update the last time if there is a NetworkTimeSystem.
114+
if (m_InternalNetworkManager.NetworkTimeSystem != null)
115+
{
116+
// Update our last sent time relative to when this was initialized
117+
UpdateLastSentTime();
118+
119+
// At this point, this instance is considered initialized
120+
HasBeenInitialized = true;
121+
}
122+
else if (m_InternalNetworkManager.LogLevel == LogLevel.Developer)
123+
{
124+
Debug.LogWarning($"[{m_NetworkBehaviour.name}][{m_NetworkBehaviour.GetType().Name}][{GetType().Name}][Initialize] {nameof(NetworkManager)} has no {nameof(NetworkTimeSystem)} assigned!");
125+
}
126+
}
127+
128+
/// <summary>
129+
/// Deinitialize is invoked when a NetworkObject is despawned.
130+
/// This allows for a recyled NetworkObject (in-scene or pooled)
131+
/// to be properly initialized upon the next use/spawn.
132+
/// </summary>
133+
internal void Deinitialize()
134+
{
135+
// When despawned, reset the HasBeenInitialized so if the associated NetworkObject instance
136+
// is recylced (i.e. in-scene placed or pooled) it will re-initialize the LastUpdateSent time.
137+
HasBeenInitialized = false;
86138
}
87139

88140
/// <summary>

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/Timing/NetworkTimeSystem.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ public void Sync(double serverTimeSec, double rttSec)
248248
var timeDif = serverTimeSec - m_TimeSec;
249249

250250
m_DesiredServerTimeOffset = timeDif - ServerBufferSec;
251-
m_DesiredLocalTimeOffset = timeDif + rttSec + LocalBufferSec;
251+
// We adjust our desired local time offset to be half RTT since the delivery of
252+
// the TimeSyncMessage should only take half of the RTT time (legacy was using 1 full RTT)
253+
m_DesiredLocalTimeOffset = timeDif + (rttSec * 0.5d) + LocalBufferSec;
252254
}
253255
}
254256
}

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

0 commit comments

Comments
 (0)