Repository navigation
Commit e9481cf
authored
feat: hybrid interop tests (#4176)
* test: add hybrid prefab prediction and interop tests
CreateHybridPrefab takes an optional GhostMode. Predicted modes are applied after NetworkObjectBridge is
added, because its editor OnValidate resets the supported ghost modes to interpolated.
HybridPredictionTests: an owner-predicted hybrid prefab predicts and re-simulates on the owning client.
HybridInteropTests combines N4E and NGO features on one hybrid prefab:
- An NGO RPC sent from PredictionUpdate repeats for re-simulated ticks, and sends each tick once when gated
on IsFirstTimeFullyPredictingTick.
- Unified remote to NGO RPC to unified remote, and NGO RPC to unified remote to NGO RPC.
- A NetworkVariable read during prediction is not tick-aligned, while a tick-stamped value applied from its
stamp tick is consistent across re-simulation.
* test: cover NetworkVariable writes from prediction and NGO ownership on hybrid prefabs
- A NetworkVariable written from PredictionUpdate moves backwards when older ticks re-simulate, and only
moves forward when gated on IsFirstTimeFullyPredictingTick.
- An NGO ownership change does not change the ghost's N4E owner.
* fix: hybrid prefab issues found by the interop tests
- UnifiedBootstrap registers the worlds it created for other NetworkManagers again after each bootstrap,
since every ClientServerBootstrap constructor clears N4E's ServerWorlds and ClientWorlds. Remote methods
send through those lists, so with several NetworkManagers in one process server-to-client remotes were
dropped.
- NetworkObjectBridge defaults a GhostObject to interpolation only when the bridge is first added, instead
of on every OnValidate, so prediction enabled on a hybrid prefab is kept.
- NGO spawn ownership and ownership changes set the ghost's owner, so an owner-predicted ghost is
predicted by its NGO owner.
- NetworkManager shutdown disposes only its own world instead of every world in the process.
NetworkObjectDontDestroyWithOwnerTests and NetworkSpawnManagerTests now run in hybrid prefab mode.
NetworkShowThenClientDisconnects is ignored for hybrid prefabs: a scene migration update can reach a
client before the object's ghost has spawned there.
* fix: set the ghost owner before OnNetworkSpawn
- The ghost owner is now assigned right after SetupOnSpawn, so OnNetworkSpawn sees the same owner on the
NetworkObject and its ghost. The interop test records the ghost owner in OnNetworkSpawn and asserts it.
- NetworkVariableReadDuringPredictionIsNotTickAligned asserts that a re-simulated tick reads a different value
than its first prediction, rather than counting reads before the stamp tick.
- NetworkShowThenClientDisconnects is only ignored for UnifiedServer, the fixture where the scene migration
failure occurs.
* fix: guard the host world in UpdateGhostOwner and wait for a re-simulation in the backwards-write test
- UpdateGhostOwner leaves the ghost unowned if a host NetworkManager has no NetcodeWorld.
- NetworkVariableWrittenFromPredictionUpdateMovesBackwards keeps writing until a backwards move has happened,
instead of stopping after 20 changes, which could come before any re-simulation.
* fix: raise the client's own disconnect event when a hybrid client disconnects
UnifiedNetcodeTransport.DisconnectLocalClient only requested the N4E disconnect. N4E reports it later, after NGO's shutdown has stopped listening, so the disconnecting client never received its ClientDisconnected event. It now notifies immediately, as UnityTransport does, and ignores N4E's later event. A server-initiated disconnect removes the connection before notifying, so the shutdown it triggers does not notify a second time.
DisconnectTests and PeerDisconnectCallbackTests now run in hybrid prefab mode.
* fix: only register hybrid instances as pending ghosts on clients in integration tests
The integration test hook that replaces GhostSpawnManager.RegisterGhostBridge also registered the server's own instance. On a dedicated server, which is never a connected client, that moved the instance into the DontDestroyOnLoad scene. The server then sent a scene migration for it to every client, and none of them had spawned it. The hook now skips the server, as the runtime does.
NetworkShowThenClientDisconnects no longer needs to be ignored for UnifiedServer.
* fix: only send scene migrations to observers, and synchronize late hybrid spawns into their scene
ObjectSceneChanged was sent to every connected client, including clients that did not observe the migrated NetworkObjects and had never spawned them, which logged "Trying to synchronize NetworkObjectId but it was not spawned". In client-server mode it is now only sent to clients that observe at least one migrated NetworkObject, and each client is only sent the NetworkObjects it observes. Distributed authority is unchanged.
A hybrid prefab instance that is part of a client's initial synchronization can spawn after the synchronization has completed, once its ghost arrives. It missed the step that migrates synchronized NetworkObjects into their server-side scene, and stayed in the active scene. It now runs that step when it spawns.
* fix: spawn a NetworkObject shown after a scene migration in the server's scene
A client that starts observing a NetworkObject with NetworkShow after the NetworkObject migrated into another scene was never sent that migration, and instantiated the NetworkObject in its active scene. The client now moves a spawned NetworkObject into its server-side scene, as it already does for NetworkObjects that are part of its initial synchronization.
Adds CHANGELOG entries for this and for scene migrations being sent to clients that do not observe the NetworkObject.
* test: collapse the DisconnectTests owner persistence fixtures into the test
Owner persistence is now set per client on the server-side player object instead of on the player prefab, so the fixtures are only Host and UnifiedHost. The host-client shutdown check runs once after both clients disconnect; before, it ran after the first client and the second client was skipped on the ClientDisconnectsFromServer path.
* fix: adapt the hybrid tests to the N4E 7.1.0 GameObject API renames
N4E 7.1.0 (unity/unity PR 126612) renamed [Remote(Directionality)] to [RPC(SendDirection)], GhostObject.IsPredictedGhost to CanWriteState, and changed GhostBehaviour.PredictionUpdate(float) to PredictionUpdate(PredictionUpdateContext).
* chore: remove stale comments from NetworkObjectBridge
The execution order TODO is already handled by DefaultExecutionOrder(GhostObject.ExecutionOrder + 1).
* style
Removing more comments.
* feat: warn when a hybrid instance sends an RPC or writes a NetworkVariable inside the prediction loop
RPCs and NetworkVariables are not part of Netcode for Entities prediction: they are not rolled back or tick aligned, so a re-simulated tick sends or writes them again. Using them from inside the prediction loop is not supported. A hybrid instance now logs one warning per NetworkBehaviour when it sends an RPC or writes a NetworkVariable while its ghost is in the prediction loop.
Replaces the HybridInteropTests cases that measured those unsupported patterns with tests for the warning, and that the same RPC and write made outside the prediction loop do not warn.
* update
1:1 With Emma.
Further simplified disconnect tests.
Made CreateHybridPrefab private.
Removed reference to unused enum.
* update
1:1 With Emma.
We both agreed this test doesn't really test anything that the HybridInteropTests validate. It is removed.
* test
Enabling the CMB service for this test.
* update
Enabling CMB server on some tests.
Making the CreateHybridPrefab internal access only for now (it is used in our hybrid prefab prediction tests).
* fix: apply the scene migration fixes in distributed authority mode
Distributed authority still sent a scene migration to every client, so clients that did not observe a migrated NetworkObject logged "Trying to synchronize NetworkObjectId but it was not spawned", and a NetworkObject shown after it migrated spawned in the client's active scene.
The owner now only sends a migration to the clients that observe a migrated NetworkObject, as in client-server mode. The CMB service's own copy still includes every migrated NetworkObject, and a migration the DAHost forwards is not filtered again. A NetworkObject a distributed authority client spawns when it is shown is moved into its owner's scene.
* chore: correct the comment on when the CMB service is sent a scene migration
Only the session owner sends the CMB service its own copy of a migration; a client that is not the session owner does not tell the service about objects only it observes.
* test
Rust server needs to be updated1 parent 3afa703 commit e9481cf
23 files changed
Lines changed: 889 additions & 158 deletions
File tree
- com.unity.netcode.gameobjects
- Runtime
- Components/Helpers
- Core
- Messaging/Messages
- NetworkVariable
- SceneManagement
- Spawning
- Transports/Unified
- Tests/Runtime
- Connection
- NetworkObject
- TestHelpers
- Unified
- testproject/Assets/Tests/Runtime/NetworkSceneManager
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | 12 | | |
14 | 13 | | |
15 | 14 | | |
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | 18 | | |
23 | 19 | | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
28 | 33 | | |
29 | 34 | | |
30 | 35 | | |
| |||
35 | 40 | | |
36 | 41 | | |
37 | 42 | | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
| |||
88 | 89 | | |
89 | 90 | | |
90 | 91 | | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
91 | 127 | | |
92 | 128 | | |
93 | 129 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
30 | 57 | | |
31 | 58 | | |
32 | 59 | | |
| |||
44 | 71 | | |
45 | 72 | | |
46 | 73 | | |
| 74 | + | |
47 | 75 | | |
48 | 76 | | |
49 | 77 | | |
| |||
69 | 97 | | |
70 | 98 | | |
71 | 99 | | |
| 100 | + | |
72 | 101 | | |
73 | 102 | | |
74 | 103 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
77 | 125 | | |
78 | 126 | | |
79 | 127 | | |
| |||
83 | 131 | | |
84 | 132 | | |
85 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
86 | 137 | | |
87 | 138 | | |
88 | 139 | | |
| |||
161 | 212 | | |
162 | 213 | | |
163 | 214 | | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
164 | 218 | | |
165 | 219 | | |
166 | 220 | | |
| |||
339 | 393 | | |
340 | 394 | | |
341 | 395 | | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
342 | 399 | | |
343 | 400 | | |
344 | 401 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1843 | 1843 | | |
1844 | 1844 | | |
1845 | 1845 | | |
1846 | | - | |
1847 | | - | |
| 1846 | + | |
| 1847 | + | |
| 1848 | + | |
| 1849 | + | |
| 1850 | + | |
1848 | 1851 | | |
1849 | 1852 | | |
1850 | 1853 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
197 | 197 | | |
198 | 198 | | |
199 | 199 | | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
200 | 207 | | |
201 | 208 | | |
202 | 209 | | |
| |||
225 | 232 | | |
226 | 233 | | |
227 | 234 | | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
228 | 241 | | |
229 | 242 | | |
230 | 243 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
281 | 281 | | |
282 | 282 | | |
283 | 283 | | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
284 | 290 | | |
285 | 291 | | |
286 | 292 | | |
| |||
0 commit comments