NetworkVariable OnValueChanged isn't invoked on clients

I’m having an issue and can’t really find what I am doing wrong.
In my project, there are two teams that can collect points. I’m storing those points inside NetworkVariables of type int. The problem is, only the server is actually registering these Value-Changes. The clients are not.

Scene placed Object containing the Network Variables:

using System;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;

public class GameModeArtifactHunt : NetworkBehaviour
{
    public delegate void OnPointsChangedDelegate(Team team, int previousValue, int newValue);
    public delegate void OnRoundsChangedDelegate(Team team, int previousValue, int newValue);
    public delegate void OnWinConditionFulfilledDelegate();

    public OnPointsChangedDelegate OnPointsChanged;
    public OnRoundsChangedDelegate OnRoundsChanged;
    public OnWinConditionFulfilledDelegate OnWinConditionFulfilled;

    [SerializeField] private float pointsPerSecond = 5f;
    public int pointsPerRound = 1200;
    public int roundsForWin = 3;

    public Dictionary<Team, NetworkVariable<int>> teamPointsDict = new Dictionary<Team, NetworkVariable<int>>();
    public Dictionary<Team, NetworkVariable<int>> teamRoundDict = new Dictionary<Team, NetworkVariable<int>>();

    private bool artifactIsHeld;
    private Team teamHoldingArtifact;
    private float currentTimer;

    void Start()
    {
        foreach (Team team in Enum.GetValues(typeof(Team)))
        {
            NetworkVariable<int> points = new NetworkVariable<int>();
            NetworkVariable<int> rounds = new NetworkVariable<int>();
            points.Value = 0;
            rounds.Value = 0;
            points.OnValueChanged += (prev, curr) =>
            {
                Debug.Log("lol"); //<--- Does not get printed on clients
                OnPointsChanged.Invoke(team, prev, curr);
            };
            rounds.OnValueChanged += (prev, curr) => OnRoundsChanged.Invoke(team, prev, curr);
            teamPointsDict.Add(team, points);
            teamRoundDict.Add(team, rounds);
        }

        DontDestroyOnLoad(this);

    }

    public void Update()
    {
        if (IsServer && artifactIsHeld)
        {
            currentTimer += Time.deltaTime;
            if (currentTimer >= 1 / pointsPerSecond)
            {
                currentTimer = 0;
                AddPoint();
            }
        }
    }

    private void AddPoint()
    {
        teamPointsDict[teamHoldingArtifact].Value += 1;
        if (teamPointsDict[teamHoldingArtifact].Value >= pointsPerRound)
        {
            teamPointsDict[Team.ORANGE].Value = 0;
            teamPointsDict[Team.PURPLE].Value = 0;
            teamRoundDict[teamHoldingArtifact].Value += 1;
            if (teamRoundDict[teamHoldingArtifact].Value >= roundsForWin)
            {
                OnWinConditionFulfilled.Invoke();
            }
        }
    }

    [ServerRpc(RequireOwnership = false)]
    public void NotifyArtifactOwnershipServerRpc(string team, ServerRpcParams serverRpcParams = default)
    {
        artifactIsHeld = true;
        teamHoldingArtifact = Enum.Parse<Team>(team);
        Debug.Log(teamHoldingArtifact);
    }

    [ServerRpc(RequireOwnership = false)]
    public void NotifyArtifactDroppedServerRpc(ServerRpcParams serverRpcParams = default)
    {
        artifactIsHeld = false;
    }
}

public enum Team
{
    ORANGE, PURPLE
}

The problem may be due to the network variables being created in Start(), I’ve only ever seen them declared as class fields.

That was the problem, thank you!

Although it’s really weird that that would be an issue… Seems strange to me.

Start is called quite late on in the creation of the network object, I would guess the network manager isn’t aware of any network variables there. It’s likely it doesn’t expect to find them anywhere except at the class level.

An older version (0.1) of the NetworkVariable manual page actually states that the NetworkVariable has to be declared as a field.

The doc also mentions that the variable should only be set in Awake or during or in OnNetworkSpawn or after spawn.