"Spawning a joiner's character clobbers the host's camera target"
▸ SYMPTOM
When a friend joins, the host's camera snaps to the joiner's character and follows it forever, while the host's own character keeps simulating and responding to input. The host sees the joiner's point of view instead of their own. The symptom reads as "my camera got stuck while I can still see my character moving when I press buttons."
▸ CAUSE
The character component is Components.Created before go.NetworkSpawn(owner) (it must be, to ride the replicated snapshot). At create time, IsProxy == false on the host for every character — including the joiner's — because the network ownership hasn't been assigned yet. If an OnEnabled callback claims a static Instance behind if (!IsProxy), the joiner's character grabs the host's camera-target singleton at create time. The host's camera then follows the wrong character.
This is the mirror case of a joining client wrongly claiming the host's character — here it happens on the host at a join-spawn.
▸ FIX
Re-resolve the Instance claim at the first OnFixedUpdate, where IsProxy is trustworthy (network ownership has been assigned):
protected override void OnFixedUpdate()
{
// A proxy that wrongly holds Instance releases it;
// the settled local owner re-claims it.
if ( IsProxy && Instance == this )
Instance = null;
else if ( !IsProxy && Instance != this )
Instance = this;
if ( IsProxy ) return;
// ... owner simulation
}A proxy that wrongly holds Instance releases it, and the real local owner re-claims it — self-healing within one tick. In single-player (never a proxy), the same code re-affirms the existing Instance, changing nothing.
▸ WHY IT WORKS
IsProxy is only reliable after NetworkSpawn completes and the networking system assigns ownership. By deferring the singleton claim to OnFixedUpdate (the first tick where ownership is settled), the claim is made based on the correct proxy state. The self-healing pattern handles any ordering edge case: even if the wrong character briefly holds the singleton, it corrects itself within a single physics tick.
Verify with a re-fetchable probe that reports which object the camera singleton points to (name, IsProxy, and owner) — a host-side pass/fail counter alone may not catch a brief camera mis-target.