Skip to content

NetworkVariable modified in OnNetworkSpawn (Server) sends default value in initial CreateObjectMessage #3876

Description

@LaPluses

The following content were rewritten by AI to improve the readability.

Root Cause Analysis was done with Gemini CLI(model: gemini-3-pro), i personally manually check on it, though am not familar with the codebase, so please treat these findings as a starting point for further validation.

Description

When a NetworkVariable is modified within the OnNetworkSpawn method on the Server immediately after spawning a NetworkObject, the connecting Client receives the default/initial value (e.g., 0) in the initial CreateObjectMessage, rather than the modified value (e.g., 2).

Although the correct value is eventually synchronized via a subsequent NetworkVariableDeltaMessage, this causes a race condition where the Client sees the incorrect value during its own OnNetworkSpawn and initial frame execution.

Reproduce Steps

  1. Create a NetworkBehaviour with a NetworkVariable<float> (default value 0).
  2. Override OnNetworkSpawn. Inside the method, check if (IsServer) and set the variable to a new value (e.g., 2).
  3. Connect a Client to the Server/Host.
  4. On the Server, Spawn an instance of this object using NetworkObject.Spawn().
  5. Observe the value of the NetworkVariable on the Client side inside the Client's OnNetworkSpawn method or immediately after spawn.
  6. See error: The Client logs/uses the default value (0) instead of the server-set value (2).

Actual Outcome

The Client receives the default value (0) in the initial spawn packet. The correct value (2) arrives late in a subsequent delta update. This breaks initialization logic dependent on the initial state of NetworkVariables.

Expected Outcome

The Client should receive the modified value (2) contained within the initial CreateObjectMessage so that OnNetworkSpawn on the client has the correct state immediately.

Screenshots

If applicable, add screenshots to help explain your problem.

Environment

  • OS: Windows
  • Unity Version: Unity 6
  • Netcode Version: 2.9
  • Netcode Commit:
  • Netcode Topology: Client-Server

Additional Context

Minimal Reproduction Code:

using Unity.Netcode;
using UnityEngine;

public class TestNetworkBehaviour : NetworkBehaviour
{
    public NetworkVariable<float> TestVal = new();

    public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();
        if (IsServer)
        {
            // Server sets the value immediately upon spawn
            TestVal.Value = 2;
        }
        else
        {
            // Client reads the value immediately
            Debug.Log($"[Client] OnNetworkSpawn TestVal = {TestVal.Value}");
            // EXPECTED: 2
            // ACTUAL: 0
        }
    }
}

Root Cause Analysis:

We have investigated the internal execution flow and identified the issue in the serialization logic relative to OnNetworkSpawn timing:

  1. Initialization: When Spawn() is called, NetworkVariable.Initialize captures the default value (0) as m_PreviousValue and sets m_HasPreviousValue = true.
  2. User Code: OnNetworkSpawn is called on the Server. The user sets TestVal.Value = 2. This marks the variable as Dirty, but m_PreviousValue remains 0.
  3. Serialization: When creating the CreateObjectMessage, NetworkVariable<T>.WriteFieldSynchronization is called.
  4. The Flaw: The logic checks:
if (base.IsDirty() && m_HasPreviousValue)
{
    // Because it is Dirty, it assumes a delta update follows.
    // It writes m_PreviousValue (which is 0) to the spawn message.
    NetworkVariableSerialization<T>.Write(writer, ref m_PreviousValue);
}
else
{
    base.WriteFieldSynchronization(writer);
}
  1. Result: The spawn message sends 0. The "new" value 2 is queued for a delta update. The client initializes with 0 before the delta arrives.

Activity

  1. added
    priority:highThis issue has high priority and we are focusing to resolve it
    stat:importStatus - Issue is going to be saved internally
    regressionThe issue is a regression (something that was working in previous version)
    and removed
    stat:awaiting-triageStatus - Awaiting triage from the Netcode team.
    on Feb 10, 2026
  2. NoelStephensUnity commented on Feb 10, 2026

    @NoelStephensUnity
    Member

    HI @LaPluses,

    Thank you for bringing this to our attention. It would seem this was a regression bug I introduced in #3799. Apologies for the inconvenience. PR #3878 should resolve this issue but is still a WIP.

    We will be releasing a hot-patch update for this once the fix has finished passing tests and been merged (i.e. you should see this pretty quickly since it is a regression issue).

  3. added
    stat:awaiting-responseAwaiting response from author. This label should be added manually.
    stat:InvestigatingIssue is currently being investigated
    and removed on Feb 10, 2026
  4. NoelStephensUnity commented on Feb 11, 2026

    @NoelStephensUnity
    Member

    @LaPluses
    Ok, PR #3878 is now completed and should be merged sometime today. Once that is done I will begin the package patch update process and promote them once that has finished. Will post here once v2.9.2 is promoted.

  5. added
    stat:importedStatus - Issue is tracked internally at Unity
    and removed
    stat:importStatus - Issue is going to be saved internally
    on Feb 11, 2026
  6. NoelStephensUnity commented on Feb 12, 2026

    @NoelStephensUnity
    Member

    @LaPluses
    At this time you should be able to update your package by name (i.e. com.unity.netcode.gameobjects) and for the version use 2.9.2. It should show up in the package manager by tomorrow.

    The fix for this issue is in both v2.8.2 and v2.9.2+.

    If you run into any problems regarding this issue please feel free to post here or to open a new issue.
    Thank you for in-depth description of the issue and your patience while I resolved this regression bug.

    Happy netcoding!

    😸

  7. LaPluses commented on Feb 12, 2026

    @LaPluses
    Author

    @NoelStephensUnity , Thank you for the incredibly quick response and for getting this fixed so fast!

    It's really a weird fundamental bug(;, appreciate your hard work(also thanks to the Gemini AI. 😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

priority:highThis issue has high priority and we are focusing to resolve itregressionThe issue is a regression (something that was working in previous version)stat:importedStatus - Issue is tracked internally at Unitytype:bugBug Report

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions