Netcode Bootstrap

This commit is contained in:
Luis Gonzalez
2026-05-31 14:27:52 -07:00
parent 99d8d2d2a9
commit 7fa77ce821
1813 changed files with 2921554 additions and 84 deletions
@@ -0,0 +1,101 @@
> 🛑 **DO NOT FILE — WITHDRAWN 2026-05-31.** This was **not** an engine bug. A clean, fresh Unity `6000.6.0a6` project (`../Local Reference`, a full Netcode-for-Entities framework) runs netcode fine on the same alpha. The failure was specific to Project M's environment (in-place 6.4→6.6 upgrade + embedded Entities-1.x `com.rukhanka.animation` package + default driver/AutoConnect path). See `Docs/Vault` DR-002 → "Correction". Kept only as a record of the investigation.
# Unity Bug Report — Netcode for Entities / Unity Transport (6000.6.0a6)
> Copy-paste into the Unity Bug Reporter (Help ▸ Report a Bug) or the Unity Discussions/issue tracker.
> Captured 2026-05-30 from Project M. Background: [[DR-002_Unity66_Alpha_Netcode_Transport]].
**Title:** [Netcode for Entities] In-editor client↔server connection never establishes — Unity Transport throws `Trying to access an invalid wrapped network interface` every frame (6000.6.0a6)
**Package(s):** Netcode for Entities `com.unity.netcode` 6.6.0 · Unity Transport `com.unity.transport` 6.6.0
**Severity:** Blocker — no Netcode-for-Entities connection can be established in the Editor; networked play is unusable.
**Unity version:** 6000.6.0a6
**Re-resolved package versions on this editor:**
- `com.unity.netcode` 6.6.0
- `com.unity.transport` 6.6.0
- `com.unity.entities` / `com.unity.collections` / `com.unity.entities.graphics` 6.5.0
- `com.unity.physics` 6.5.0
- `com.unity.burst` 1.8.29 · `com.unity.mathematics` 1.4.0
**Environment:** macOS (Apple Silicon), `OSXEditor`, URP 17.6. In-Editor (not batch mode).
---
## Description
Any standard Netcode-for-Entities setup that creates a `ServerWorld` + `ClientWorld` and auto-connects (the default `ClientServerBootstrap` with `AutoConnectPort` set, `RequestedPlayType = ClientAndServer`) **fails to ever establish a connection in the Editor**. The client creates a `NetworkStreamConnection` entity, but the server never accepts it and **no `NetworkId` is ever assigned** to either side.
Every frame, the Console floods with:
```
Exception thrown in a managed function called from unmanaged code:
System.InvalidOperationException: Trying to access an invalid wrapped network interface.
```
When the Jobs Debugger is enabled, this is accompanied by a cascade of dependency-safety exceptions across Unity Transport's internal layered-driver jobs, e.g.:
```
InvalidOperationException: The previously scheduled job NetworkDriver:UpdateJob writes to the
Unity.Collections.NativeList`1[...]. You are trying to schedule a new job
SimpleConnectionLayer:ReceiveJob`1 / SequenceReorderingLayer:ReceiveJob / TopLayer:CompleteReceiveJob /
AnalyticsLayer:AnalyticsJob / BottomLayer:ClearJob / RpcSystem:RpcExecJob ...
To guarantee safety, you must include NetworkDriver:UpdateJob as a dependency of the newly scheduled job.
```
and subsequently:
```
[Netcode] Server Tick Batching has occurred due to the server falling behind its desired SimulationTickRate ...
```
**Disabling the Jobs Debugger** (`JobsUtility.JobDebuggerEnabled = false`) removes the dependency-safety exceptions, but the **`Trying to access an invalid wrapped network interface`** error persists and the connection still never forms — so the invalid network interface is the root cause, independent of the safety checks.
## Steps to reproduce (minimal — no gameplay content required)
1. New project on **6000.6.0a6**; add `com.unity.netcode` (6.6.0; Entities 6.5.0 / Transport 6.6.0 resolve automatically).
2. Add this bootstrap (the only script needed):
```csharp
using Unity.Entities;
using Unity.NetCode;
using UnityEngine.Scripting;
[Preserve]
public class TestBootstrap : ClientServerBootstrap
{
public override bool Initialize(string defaultWorldName)
{
AutoConnectPort = 7979; // in-editor auto-connect (ClientAndServer, IPC)
CreateDefaultClientServerWorlds();
return true;
}
}
```
3. Open any scene — an **empty scene** (camera + light only; no SubScene, no ghosts, no systems) is sufficient.
4. Enter Play Mode.
## Expected
The in-process client connects to the server over IPC; the server assigns a `NetworkId`; a `NetworkStreamConnection` is established on both worlds. No Transport exceptions.
## Actual
No connection forms.
- `ServerWorld`: 0 `NetworkStreamConnection`, 0 `NetworkId`.
- `ClientWorld`: 1 `NetworkStreamConnection`, **0 `NetworkId`**.
- Console floods every frame with `Trying to access an invalid wrapped network interface` (plus Transport job-safety exceptions when the Jobs Debugger is on).
## Frequency
100% reproducible. Occurs with **zero gameplay content** (empty scene + the bootstrap above), confirming it is not project-specific.
## Regression / likely cause
- Netcode for Entities + Unity Transport are transitioning to built-in Core packages (since 6000.5.0a7), which renumbered them into the 6.x editor line.
- The **6000.6.0a5** changelog states Netcode snapshots were reworked to use Unity Transport's *"unreliable sequenced pipeline"* — the same `SequenceReorderingLayer` / layered-driver path that throws here. The regression appears to coincide with that rework.
## Known-good baseline
The same setup works on **Unity 6.4.x** (Netcode for Entities 1.13.2 / Unity Transport 2.7.2).
+8 -1
View File
@@ -13,11 +13,18 @@ permalink: gamevault/01-vision/pillars
## Pillars
- _TBD — define the 35 experiential pillars of Project M._
1. **Action-ARPG combat** — twin-stick, controller-first (LoL / Diablo 4 / PoE2 feel); skill expression over stat-checks.
2. **Co-op base power fantasy** — 24 friends build and grow a shared home base (V Rising feel).
3. **Automation as progression** — production runs itself so play time compounds; the loop rewards setup, not grind.
4. **Server-authoritative & deterministic** — input-only clients, client prediction; the simulation is the source of truth.
## Locked decisions
- **Tech stack:** Unity DOTS (Entities) + Netcode for Entities — server-authoritative, input-only clients, client prediction. Established [[2026-05-29_Project_Setup]].
- **Control (locked 2026-05-30):** WASD movement, controller-first, **directional / twin-stick aim** with soft auto-target in-arc. [[2026-05-30_M1_Player_Slice]]
- **Multiplayer (locked):** small co-op **24, client-hosted listen-server** (BinaryWorlds + in-proc IPC; not the experimental SingleWorld host mode), PvE.
- **World (locked):** persistent buildable **home base + instanced/procedural expeditions**.
- **Automation (locked):** **progression accelerator** — self-running production chains; data model designed to grow toward full logistics.
## Related
+5 -1
View File
@@ -12,7 +12,11 @@ One design doc per gameplay system, linked here. Each should state: purpose, com
## Systems
- _None yet._
### M1 — Player (twin-stick predicted movement) · [[2026-05-30_M1_Player_Slice]]
- **Components** (`ProjectM.Simulation`): `PlayerTag`; `PlayerInput` (IInputComponentData — `float2` Move/Aim, `[GhostField]`, flows via AutoCommandTarget); `PlayerMoveStats` (baked tunables); `PlayerFacing` (`[GhostField]` Direction); `PlayerSpawner` (baked prefab singleton); `GoInGameRequest` (IRpcCommand).
- **Systems:** `PlayerMoveSystem`, `PlayerAimSystem` (`PredictedSimulationSystemGroup`, `.WithAll<Simulate>()`, deterministic — `SystemAPI.Time.DeltaTime` only); `PlayerInputGatherSystem` (client, `GhostInputSystemGroup`); `GoInGameClientSystem` (client) / `GoInGameServerSystem` (server — spawns the owner-predicted ghost, stamps `GhostOwner`, `LinkedEntityGroup` auto-despawn).
- **Netcode shape:** player = **owner-predicted** ghost; client sends input only; server is authoritative. Status: **code-complete + EditMode-verified**; live runtime blocked by [[DR-002_Unity66_Alpha_Netcode_Transport]].
## Conventions
+7 -3
View File
@@ -10,7 +10,11 @@ permalink: gamevault/06-roadmap/backlog
Unordered pool of candidate work. Promote to a [[Milestones|milestone]] when committed.
- [ ] Decide whether to upgrade Unity 6.4 → 6.6 for newer Entities (6.6.x). Stack is forward-compatible; `NetCodeTestWorld` stays internal regardless — see [[DR-001_Netcode_Test_Harness]].
- [ ] Define the core gameplay loop and the first predicted player ghost.
- [x] Upgrade Unity 6.4 → 6.6 — done (now `6000.6.0a6`). Entities/Collections/Graphics → 6.5.0; **Netcode → 6.6.0 and Physics → 6.5.0 also renumbered into the editor line** (not independent 1.x as [[DR-001_Netcode_Test_Harness]] assumed). See [[2026-05-30_M1_Player_Slice]].
- [x] Define the core gameplay loop and the first predicted player ghost — delivered as M1 ([[2026-05-30_M1_Player_Slice]]).
- [ ] **Re-validate the M1 play-tick on a stable Unity 6.x** — live runtime blocked on the 6.6 alpha ([[DR-002_Unity66_Alpha_Netcode_Transport]]); optionally reproduce with the `networked-cube` sample to file a bug.
- [ ] Replace template `SampleScene` with a dedicated bootstrap scene + gameplay subscene.
- [ ] Optional template cleanup: remove `com.unity.visualscripting`, `Assets/TutorialInfo/`, `Assets/Readme.asset` (delete each asset **with** its `.meta`).
- [ ] Optional template cleanup: remove `com.unity.visualscripting`, `Assets/TutorialInfo/`, `Assets/Readme.asset` (delete each asset **with** its `.meta`).
- [ ] Decide **relay provider** (default Unity Relay) before M3.
- [ ] Decide home-base **grid 2D vs 3D** before M5.
- [ ] Decide **production replication** (predicted vs server-only) before M6.
+6 -1
View File
@@ -11,6 +11,11 @@ permalink: gamevault/06-roadmap/milestones
| Milestone | Goal | Status |
|---|---|---|
| **M0 — Foundation** | DOTS + Netcode stack, asmdef split, bootstrap, smoke test green | ✅ Done 2026-05-29 — [[2026-05-29_Project_Setup]] |
| **M1 — _TBD_** | Define the first playable slice (core loop + first predicted ghost) | ⬜ |
| **M1 — Player slice** | Server-spawned owner-predicted player; twin-stick WASD + directional aim | ✅ Done 2026-05-31 — runtime-validated on Unity 6.4.7 (connect→spawn→owner-predicted ghost→replication; EditMode 3/3). The 6.6 failure was environment-specific, see [[DR-002_Unity66_Alpha_Netcode_Transport]] — [[2026-05-30_M1_Player_Slice]] |
| **M2 — Combat** | Directional ability fire + deterministic soft auto-target; server-authoritative damage/health | ⬜ |
| **M3 — Co-op** | 24 players; client-hosted listen-server over Unity Relay | ⬜ |
| **M4 — Home base + physics** | Persistent base subscene streaming + Unity Physics in the predicted loop | ⬜ |
| **M5 — Build/placement** | Server-authoritative grid build placement via RPC | ⬜ |
| **M6 — Automation** | Self-running tick-based production chains (deterministic offline catch-up) | ⬜ |
Promote items from [[Backlog]] here when committed.
@@ -0,0 +1,50 @@
---
date: 2026-05-30
type: session
tags: [session, dots, netcode, m1]
permalink: gamevault/07-sessions/2026/2026-05-30-m1-player-slice
---
# Session 2026-05-30 — M1 Player Slice + foundation direction
## Goal
Kick off real dev via `/dots-dev`: lock the genre/foundation direction for a **V Rising × factory-automation co-op ARPG** (small team), plan the initial phases, and build **M1** — a server-spawned, owner-predicted player ghost that moves via twin-stick WASD + directional aim.
## Done
### Direction locked — see [[Pillars]]
- **Genre:** V Rising mechanics + action-ARPG combat (LoL / Diablo 4 / PoE2) + factory automation; small-team scope.
- **Control:** WASD movement, controller-first, **directional / twin-stick** aim (soft auto-target in-arc).
- **Multiplayer:** small co-op **24, client-hosted listen-server** (BinaryWorlds + in-proc IPC), PvE.
- **World:** persistent buildable **home base + instanced/procedural expeditions**.
- **Automation:** **progression accelerator** — self-running production chains; data model designed to grow toward full logistics.
- 6-phase roadmap M1M6 — see [[Milestones]].
### M1 built — code-complete, EditMode-verified
All four asmdefs compile clean (source-gen OK); EditMode tests **3/3 green**.
- **Simulation:** `PlayerTag`, `PlayerInput` (IInputComponentData, `float2` Move/Aim `[GhostField]`, `ToFixedString`), `PlayerMoveStats`, `PlayerFacing` (`[GhostField]` Direction), `GoInGameRequest` (IRpcCommand), `PlayerSpawner`; `PlayerMoveSystem` + `PlayerAimSystem` (PredictedSimulationSystemGroup, `.WithAll<Simulate>()`, `SystemAPI.Time.DeltaTime` only — deterministic).
- **Client:** `GoInGameClientSystem`; `PlayerInputGatherSystem` (GhostInputSystemGroup, non-Burst ISystem reading the Input System).
- **Server:** `GoInGameServerSystem` (instantiate player + `GhostOwner` from `NetworkId` + `LinkedEntityGroup` auto-despawn).
- **Authoring/asset:** `PlayerAuthoring` / `PlayerSpawnerAuthoring` bakers; `Player.prefab` (GhostAuthoringComponent **OwnerPredicted**, HasOwner, AutoCommandTarget); `PlayerSpawner` wired into `Gameplay.unity`; `GameBootstrap.AutoConnectPort = 7979`.
- **Tests:** `PlayerMoveSystemTests` — deterministic advance + idempotence across tick batches.
- Live Netcode 6.6 API shapes verified via `unity_reflect` before coding (`GhostOwner.NetworkId`, `NetworkId.Value`, `Receive`/`SendRpcCommandRequest`, `GhostOwnerIsLocal`, `IInputComponentData.ToFixedString``FixedString512Bytes`).
### Build gotchas learned — now in repo `CLAUDE.md`
- Source-gen'd systems need **`Unity.Transforms`** as a *direct* asmdef reference (`LocalTransform`); transitive visibility doesn't satisfy the generator.
- Authoring asmdefs need **`Unity.Entities.Hybrid`** (for `Baker<T>`) and **`Unity.Collections`**.
- A component named **`PlayerInput`** collides with `UnityEngine.InputSystem.PlayerInput`; with `using UnityEngine.InputSystem;` the Entities generator binds `RefRW<PlayerInput>` to the *managed* class → misleading **CS8377** "must be unmanaged". Fix: fully-qualify Input System types, don't import the namespace.
- A nested baker class must not be named `Baker` (shadows `Unity.Entities.Baker<T>` → CS0308/CS0246).
## Decisions
- [[DR-002_Unity66_Alpha_Netcode_Transport]] — runtime netcode is blocked on the 6.6 alpha.
- **Host mode = BinaryWorlds + IPC** (stable), not the experimental `HostWorldMode.SingleWorld` (internal unless `NETCODE_EXPERIMENTAL_SINGLE_WORLD_HOST`).
- Correction to [[DR-001_Netcode_Test_Harness]] assumption: on the 6.6 upgrade, **Netcode (→6.6.0) and Physics (→6.5.0) DID renumber** into the editor line — they did **not** stay independent 1.x. `CLAUDE.md` updated.
## Open / deferred
- **BLOCKER — env-specific, NOT an engine bug (corrected 2026-05-31):** the in-editor connection never formed on Project M @ `6000.6.0a6` ("invalid wrapped network interface"). Initially mis-attributed to a Unity engine bug, but a **clean fresh `6000.6.0a6` project (`../Local Reference`, a full Netcode-for-Entities framework) connects fine**. The bare-scene repro still ran inside Project M's contaminated environment (embedded Entities-1.x `rukhanka` + in-place-upgrade `Library`/manifest residue + default driver/AutoConnect), so it isolated gameplay code but not the environment. Bug report withdrawn. See [[DR-002_Unity66_Alpha_Netcode_Transport]] → Correction.
- **RESOLVED 2026-05-31:** M1 runtime **fully validated on Unity 6.4.7 / Netcode 1.13.2** — connect → GoInGame → server-spawn → owner-predicted ghost → client replication all confirmed (`players=1`/`netIds=1`/`inGame=1`/`ownerLocal=1` in both worlds), no transport error. One-time fix: forced asset reimport to rebake the stale entity-subscene after the in-place downgrade. Minor follow-ups: enable `Application.runInBackground`; re-save URP global settings (cosmetic missing-types from the 17.6→17.4 downgrade).
- Deferred decisions (revisit at their phase): **relay provider** (default Unity Relay) before M3; home-base **grid 2D vs 3D** before M5; **production predicted vs server-only** before M6; **character controller** (custom kinematic vs vendor ECS-samples) at M4.
## Next
Re-run the M1 play-tick on a **stable Unity 6.x** (or reproduce with the `networked-cube` sample to file a bug). When green, proceed to **M2 — twin-stick combat / abilities**.
@@ -0,0 +1,68 @@
---
id: DR-002
title: Unity 6.6.0-alpha Netcode/Transport runtime regression blocks in-editor play-tick
status: superseded
date: 2026-05-30
superseded: 2026-05-31 — see Correction below
tags:
- decision
- netcode
- transport
- engine
permalink: gamevault/07-sessions/decisions/dr-002-unity66-alpha-netcode-transport
---
# DR-002 — Unity 6.6.0-alpha Netcode/Transport runtime regression
> ⚠️ **SUPERSEDED 2026-05-31 — this was NOT a universal engine bug. See "## Correction" at the bottom.** A clean, fresh Unity `6000.6.0a6` project (`../Local Reference`) runs Netcode for Entities successfully. The failure was specific to **Project M's environment** (in-place 6.4→6.6 upgrade + embedded `com.rukhanka.animation` Entities-1.x package + default driver/AutoConnect path), not Unity itself. The drafted Unity bug report should **not** be filed.
## Context
The project runs on **Unity `6000.6.0a6`** (6.6.0 **alpha**) with `com.unity.netcode` 6.6.0, `com.unity.transport` 6.6.0, `com.unity.entities`/`collections`/`graphics` 6.5.0, `com.unity.physics` 6.5.0.
Building [[2026-05-30_M1_Player_Slice|M1]], the code compiled clean and EditMode tests passed (3/3), but the in-editor two-world play-tick **never establishes a network connection** (`NetworkId` connection count stays 0; no player ghost spawns). Every frame the console floods with exceptions located **entirely inside Unity packages**:
- `com.unity.transport`: `System.InvalidOperationException: Trying to access an invalid wrapped network interface.` (dominant, ~20×/sample)
- A cascade of Jobs-Debugger dependency-safety violations across Transport's internal layer jobs: `NetworkDriver:UpdateJob`, `SimpleConnectionLayer`, `SequenceReorderingLayer`, `AnalyticsLayer`, `BottomLayer`/`TopLayer`, `RpcSystem:RpcExecJob` ("you must include X as a dependency of the newly scheduled job").
- `com.unity.netcode`: "Server Tick Batching … falling behind its desired `SimulationTickRate`".
No `ProjectM.*` code appears in any stack trace. Reproduced across two clean play sessions. Disabling the Jobs Debugger (`JobsUtility.JobDebuggerEnabled = false`) removed the job-safety exceptions, but the **"invalid wrapped network interface"** persisted and the connection still never formed — so the root failure is Transport network-interface initialization, not the safety checks.
## Decision
Treat this as an **engine-alpha regression**, not an M1 code defect. M1 is **code-complete and statically verified**: clean compile + source-gen, EditMode determinism tests green, both `ServerWorld`/`ClientWorld` boot with correct flags. Runtime validation of the connect → spawn → predicted-move loop is **deferred to a stable Unity 6.x build**.
## Consequences
- Do **not** burn effort debugging Transport internals from game code; the fault is below our layer.
- Tracked action items: (1) re-run the M1 play-tick on a stable Unity 6.x; (2) optionally reproduce with Unity's own `networked-cube` sample to confirm + file a bug.
- Until resolved, treat in-editor netcode **runtime** on `6000.6.0a6` as unreliable; rely on plain-Entities EditMode tests (see [[DR-001_Netcode_Test_Harness]]) for deterministic logic coverage.
- **Recommendation:** for netcode runtime work, prefer a **stable** Unity 6.x release over the alpha.
## Confirmation — clean-room repro (2026-05-30)
Reproduced with **zero Project M code**: a fresh empty scene (camera + light only — no Gameplay subscene, no ghosts/components/systems) where Unity's canonical bootstrap creates `ServerWorld` + `ClientWorld` and auto-connects. The identical `Trying to access an invalid wrapped network interface` flood appears; `ClientWorld` opens a `NetworkStreamConnection` but the server never accepts and **no `NetworkId` is assigned** on either side. ⇒ the fault is entirely in Unity Transport/Netcode, not our gameplay or bootstrap logic.
## Web corroboration
- Netcode for Entities + Unity Transport are **mid-migration to built-in (Core) packages bundled with the Editor, since Unity `6000.5.0a7`** — which is why they renumbered into the 6.x line on our upgrade. ([status update](https://discussions.unity.com/t/netcode-for-entities-and-unity-transport-status-update/1707400))
- The netcode↔transport pipeline was **actively reworked this alpha cycle**: the `6000.6.0a5` changelog states "Netcode for Entities snapshots now use Unity Transport's unreliable sequenced pipeline instead of a home-baked solution." That unreliable-sequenced / `SequenceReorderingLayer` path is exactly what throws in our logs.
- Transport's `NetworkDriver.Concurrent` multi-job safety behaviour has acknowledged rough edges (Unity Transport maintainer, Jan 2026, Transport 2.6 / Unity 6.3) with no fix. ([thread](https://discussions.unity.com/t/using-the-same-networkdriver-concurrent-in-two-jobs-causes-an-error/1703439))
- **No public report matches the exact `invalid wrapped network interface` connection-blocking failure on `6000.6.0a6`** — consistent with an unreported in-flight alpha regression. Worth **filing a Unity bug** with the minimal bare-scene repro above.
## Resolution (2026-05-30)
**Reverting the project to Unity 6.4.7** (Netcode for Entities 1.13.2 / Transport 2.7.2 — the known-good baseline) to unblock runtime netcode. A file-ready bug report was drafted at `Docs/UnityBugReport-Netcode-Transport-6.6.0a6.md`. Next: re-validate the M1 connect→spawn→predicted-move loop on 6.4 (the M1 code should port with no/minimal changes — recompile + `read_console`). Revisit Unity 6.6 once the Transport regression is fixed in a later alpha/beta.
## Correction (2026-05-31)
The "confirmed engine bug" conclusion above is **withdrawn**. A side-by-side file diff against a fresh project (`Projects/Rain/Games/Unity/Local Reference`) showed:
- **`Local Reference` is a clean Unity `6000.6.0a6` Netcode-for-Entities framework project** (dedicated-server bootstraps, GhostBridge ghost framework, prediction, **its own custom `EntityDriverConstructor`** + explicit connect flow) — and it runs netcode successfully on the same alpha.
- **Project M @ 6.6 differed in three ways the template does not have:** (1) an embedded third-party **`com.rukhanka.animation` 2.9.0** built for **Unity 2022.3 / Entities 1.x** (depends on `entities.graphics 1.4.16`); (2) it was **upgraded in-place 6.4→6.6** (stale `Library/` + leftover/mixed `manifest.json` pins); (3) it used the **default `IPCAndSocketDriverConstructor` + `AutoConnectPort`**, whereas the template uses a custom driver constructor.
**Why my repro misled me:** the "bare scene" repro still ran inside Project M's contaminated environment (rukhanka + dirty `Library` load regardless of scene), so it isolated *gameplay code* but not the *project environment*. The correct control — a clean 6.6 project — works.
**Revised stance:** environment-specific, not an engine bug. **Do not file the Unity bug.** Candidate causes (unranked, not yet isolated): stale upgrade `Library`, the Entities-1.x `rukhanka` package, the default-driver/AutoConnect path, manifest-pin inconsistency. **To run on 6.6:** clean a 6.6 Project M (remove/replace rukhanka, delete `Library/` + reimport, reconcile manifest pins) and re-test. Project M is currently on **6.4.7** (stable baseline) where M1 should run regardless.
**Confirmed 2026-05-31:** M1 runtime **works on Unity 6.4.7** — the full connect → GoInGame → server-spawn → owner-predicted ghost → client replication loop validated (1 player ghost in both worlds, no transport error). This + the working clean 6.6 template settles it: the 6.6 failure was **environment-specific**, not an engine bug. (Note: the in-place 6.6→6.4.7 downgrade left a stale entity-subscene cache that hung the first play-mode entry until a forced reimport rebaked it — the same in-place-version-change dirtiness lesson.)