You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 15166f7
Browse filesBrowse the repository at this point in the historyBrowse files
fix: hybrid prefab component gating and distributed authority rejection (#4184)
* fix: gate hybrid prefab components instead of destroying them
A hybrid prefab's NetworkRigidbodyBase derivatives were destroyed at runtime so a user could
try hybrid mode without first stripping components from the prefab. Removing an entry from
ChildNetworkBehaviours is not safe: InitializeChildNetworkBehaviours rebuilds unconditionally
and has five call sites, two of them the public GetNetworkBehaviourOrderIndex and
GetNetworkBehaviourAtOrderIndex, while Destroy is deferred to end of frame. A rebuild in a
later frame therefore renumbers every behaviour after the removed one, and the NetworkVariable
half of object synchronization is positional with no id, so a one-entry disagreement corrupts
the whole buffer for that object.
NetworkTransform was already handled by early-returning on HasGhost rather than being
destroyed - the removal behind UNIFIED_NETCODE_DESTROY was dead, that define exists nowhere.
This extends the same treatment to NetworkRigidbodyBase and closes four NetworkTransform paths
that had no gate: OnSynchronize, InternalOnNetworkPostSpawn,
InternalOnNetworkSessionSynchronized and InternalOnNetworkObjectParentChanged. The first of
those means a hybrid object no longer writes a full teleport state to every joining client.
The rigidbody is now forced kinematic on non-server peers rather than destroyed, restored from
m_OriginalKinematicState on destroy as the class already provided for. That decision is made at
spawn, not during Awake, because Initialize runs from Awake where an in-scene placed instance
has no session to ask whether it is the server. UnregisterRigidbody had no call sites and is
now called from the gate, which is what keeps a second Initialize from leaving a registration
pointing at a component that no longer drives anything.
[RequireComponent(typeof(Rigidbody))] is unconditional again. Behind #if !UNIFIED_NETCODE it
was stripped from every NetworkRigidbody in the project the moment N4E was installed, hybrid or
not, after which NetworkRigidbodyBase dereferences a null rigidbody in Awake.
* fix: reject hybrid prefabs in distributed authority sessions
Distributed authority does not support hybrid prefabs. A start with any GhostObject prefab
registered now fails in CanStart with an error naming each prefab, before Initialize replaces
the transport with UnifiedNetcodeTransport. A hybrid prefab added during a distributed
authority session is refused, so HasGhostPrefabs cannot switch the running session into
hybrid mode and stop its send queue.
* fix: address u-pr review and reject hybrid prefab overrides
- NetworkRigidbodyBase no longer re-applies the authority kinematic rule on an ownership change for a hybrid prefab.
- NetworkPrefabs recomputes HasGhostPrefabs on initialize, and keeps a single subscription to each NetworkPrefabsList
(a prefab added to a list during a session was registered more than once).
- RejectGhostPrefabs is set in Initialize, after SetRole accepts the start, so a failed start cannot leave it set.
- A NetworkPrefab override with a hybrid source or target prefab is detected as a hybrid registration. N4E
instantiates the server's prefab from the ghost type, so overrides are not supported for hybrid prefabs yet: a start
with one registered fails in any topology, and one added during a session is rejected.
* fix: address review on hybrid prefab validation
- Move the distributed authority hybrid prefab check and its session flag into NetworkPrefabs, called through NetworkConfig.InitializePrefabsForStart.
- NetworkPrefab.Validate treats an override with a hybrid source or target as invalid, so it is logged and ignored in any topology.
- Add NetworkPrefab.GetDebugName, used by the prefab logs and the debugger.
- Add NetcodeIntegrationTest.CreateNetworkObjectPrefab(string, bool).
- Trim the hybrid prefab tests to the behaviour id and kinematic checks, and rework the validation tests onto the harness helpers.
* test: remove BehaviourIdsMatchOnAllPeers
KinematicStateSurvivesOwnershipChange already runs the same behaviour table and gated component checks.
Copy file name to clipboardExpand all lines: com.unity.netcode.gameobjects/CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,6 +18,8 @@ Additional documentation and release notes are available at [Multiplayer Documen
18
18
19
19
### Fixed
20
20
21
+
- Fixed issue where a prefab added to a `NetworkPrefabsList` while a session was running was registered more than once and logged a duplicate `GlobalObjectIdHash` error. (#4184)
Copy file name to clipboardExpand all lines: com.unity.netcode.gameobjects/Runtime/Components/NetworkRigidBodyBase.cs
+85-27Lines changed: 85 additions & 27 deletions
Original file line number
Diff line number
Diff line change
@@ -21,13 +21,6 @@ public abstract class NetworkRigidbodyBase : NetworkBehaviour
21
21
internalboolNetworkRigidbodyBaseExpanded;
22
22
#endif
23
23
24
-
// TODO-UNIFIED:
25
-
// Provide an option to automatically remove the NetworkRigidbodyBase component at runtime if it is a hybrid prefab that is spawned since this
26
-
// component is primarily used for the Rigidbody interpolation and extrapolation features of NetworkTransform which are not relevant for a hybrid
27
-
// prefab that is spawned since it will be using N4E's built in interpolation and extrapolation features. This greatly improves performance on
28
-
// the client side. If using N4E prediction or distributed authority mode, then Rigibody and any component derived from this should always be used.
29
-
30
-
31
24
/// <summary>
32
25
/// When enabled, the associated <see cref="NetworkTransform"/> will use the Rigidbody/Rigidbody2D to apply and synchronize changes in position, rotation, and
33
26
/// allows for the use of Rigidbody interpolation/extrapolation.
// Keep track of the original kinematic state. (see OnDestroy)
264
-
m_OriginalKinematicState=IsKinematic();
265
-
#endif
266
271
SetIsKinematic(true);
267
272
}
268
273
}
274
+
#endif
269
275
270
276
#if UNIFIED_NETCODE
277
+
// The authored kinematic state, restored in OnDestroy.
278
+
privateboolm_OriginalKinematicState;
279
+
280
+
/// <summary>
281
+
/// Skips initialization on a hybrid prefab, whose GhostObject drives its motion. The component stays so <see cref="NetworkBehaviour.NetworkBehaviourId"/> values match on every peer.
282
+
/// </summary>
283
+
/// <returns>true for a hybrid prefab</returns>
284
+
privateboolInitializeHybrid()
285
+
{
286
+
if(NetworkObject==null||!NetworkObject.HasGhost)
287
+
{
288
+
returnfalse;
289
+
}
290
+
291
+
// Clears any registration left behind by a prior Initialize call.
292
+
if(NetworkTransform!=null)
293
+
{
294
+
NetworkTransform.UnregisterRigidbody();
295
+
}
296
+
297
+
m_OriginalKinematicState=IsKinematic();
298
+
returntrue;
299
+
}
300
+
301
+
/// <summary>
302
+
/// Kinematic on every peer except the server. Called at spawn because an in-scene placed instance has no session during Awake.
303
+
/// </summary>
304
+
privatevoidSetHybridKinematicState()
305
+
{
306
+
if(!m_LocalNetworkManager.IsServer)
307
+
{
308
+
SetIsKinematic(true);
309
+
}
310
+
}
311
+
312
+
/// <inheritdoc/>
271
313
publicoverridevoidOnDestroy()
272
314
{
273
315
base.OnDestroy();
274
-
// If the user has left this component on their prefab and this is a hybrid prefab,
275
-
// then we want to set the rigid body back to its original kinematic settings since
276
-
// we are automatically destroying these components at runtime when it is a hybrid
0 commit comments