Leaderboard Update

Hi,
I cannot find the solution to my Updating problem.
When I add a second player, the leaderbaord display on the second player does not get the totalCoin from the first player. They are both at 0 even if I gathered 30 coins beforehand. When the first player gather a new coin, the leaderboard (on the second player window) update fine. The host player is always fine.

public class LeaderBoardScript : NetworkBehaviour
{
    [SerializeField] private Transform leaderBoardEntityHolder;
    [SerializeField] private LeaderBoardEntityDisplay leaderBoardEntityPrefab;
    [SerializeField] private int entitiesToDisplay = 4;

    private NetworkList<LeaderboardEntityState> leaderboardEntities;
    private List<LeaderBoardEntityDisplay> entitiesDisplays = new List<LeaderBoardEntityDisplay> ();

    private void Awake()
    {
        leaderboardEntities = new NetworkList<LeaderboardEntityState>();
    }

    public override void OnNetworkSpawn()
    {
        if(IsClient)
        {
            leaderboardEntities.OnListChanged += HandleLeaderboardEntitiesChanged;
            foreach(LeaderboardEntityState entity in leaderboardEntities)
            {
                HandleLeaderboardEntitiesChanged(new NetworkListEvent<LeaderboardEntityState>
                {
                    Type = NetworkListEvent<LeaderboardEntityState>.EventType.Add, 
                    Value = entity
                }) ;
            }
        }
        if (IsServer) 
        {
            TankPlayer[] players = FindObjectsByType<TankPlayer>(FindObjectsSortMode.None);

            foreach (TankPlayer player in players)
            {
                HandlePlayerSpawned(player);
            }

            TankPlayer.OnPlayerSpawned += HandlePlayerSpawned;
            TankPlayer.OnPlayerDespawned += HandlePlayerDespawned;
        }
        
    }
    public override void OnNetworkDespawn()
    {
        if (IsClient)
        {
            leaderboardEntities.OnListChanged -= HandleLeaderboardEntitiesChanged;
        }
        if (IsServer)
        {
            TankPlayer.OnPlayerSpawned -= HandlePlayerSpawned;
            TankPlayer.OnPlayerDespawned -= HandlePlayerDespawned;
        }
        
    }
    private void HandlePlayerSpawned(TankPlayer player)
    {
        leaderboardEntities.Add( new LeaderboardEntityState
        {
            ClientId = player.OwnerClientId,
            PlayerName = player.PlayerName.Value,
            Coins = 0
        }
            );

        player.Wallet.TotalCoin.OnValueChanged += (oldCoins, newCoins) => HandleCoinChanged(player.OwnerClientId, newCoins);
    }
    private void HandlePlayerDespawned(TankPlayer player) 
    {
        if (leaderboardEntities == null) { return; }

        foreach(LeaderboardEntityState entity in leaderboardEntities)
        {
            if(entity.ClientId != player.OwnerClientId) { continue; }

            leaderboardEntities.Remove( entity );
            break;
        }
        player.Wallet.TotalCoin.OnValueChanged -= (oldCoins, newCoins) => HandleCoinChanged(player.OwnerClientId, newCoins);
    }
    private void HandleLeaderboardEntitiesChanged(NetworkListEvent<LeaderboardEntityState> changeEvent)
    {
        switch (changeEvent.Type)
        {
            case NetworkListEvent<LeaderboardEntityState>.EventType.Add:
                if (!entitiesDisplays.Any(x => x.ClientId == changeEvent.Value.ClientId))
                {
                    LeaderBoardEntityDisplay leaderboardEntityDisplay = Instantiate(leaderBoardEntityPrefab, leaderBoardEntityHolder);
                    leaderboardEntityDisplay.Initialise(
                        changeEvent.Value.ClientId, 
                        changeEvent.Value.PlayerName, 
                        changeEvent.Value.Coins);
                    entitiesDisplays.Add( leaderboardEntityDisplay );
                }
                break;
            case NetworkListEvent<LeaderboardEntityState>.EventType.Remove:
                LeaderBoardEntityDisplay lbed = entitiesDisplays.FirstOrDefault(x => x.ClientId == changeEvent.Value.ClientId);
                if (lbed != null)
                {
                    lbed.transform.SetParent(null);
                    Destroy(lbed.gameObject);
                    entitiesDisplays.Remove( lbed );
                }
                break;
            case NetworkListEvent<LeaderboardEntityState>.EventType.Value:
                LeaderBoardEntityDisplay lbeuPdate = entitiesDisplays.FirstOrDefault(x => x.ClientId == changeEvent.Value.ClientId);
                if (lbeuPdate != null)
                {
                    lbeuPdate.UpdateCoins(changeEvent.Value.Coins);
                }
                break;
        }

        entitiesDisplays.Sort((x, y) => y.Coins.CompareTo(x.Coins));
        for(int i=0;i<entitiesDisplays.Count; i++)
        {
            entitiesDisplays[i].transform.SetSiblingIndex(i);
            entitiesDisplays[i].UpdateText();
            bool shouldShow = i <= entitiesToDisplay - 1;
            entitiesDisplays[i].gameObject.SetActive(shouldShow);
        }
        LeaderBoardEntityDisplay myDisplay = entitiesDisplays.FirstOrDefault(x => x.ClientId == NetworkManager.Singleton.LocalClientId);
        if(myDisplay != null)
        {
            if(myDisplay.transform.GetSiblingIndex() > entitiesToDisplay)
            {
                leaderBoardEntityHolder.GetChild(entitiesToDisplay-1).gameObject.SetActive(false);
                myDisplay.gameObject.SetActive(true);
            }
        }

    }

    private void HandleCoinChanged(ulong clientId, int newCoins)
    {
        for(int i = 0; i < leaderboardEntities.Count; i++)
        {
            if (leaderboardEntities[i].ClientId != clientId) { continue; }

            leaderboardEntities[i] = new LeaderboardEntityState
            {
                ClientId = leaderboardEntities[i].ClientId,
                PlayerName = leaderboardEntities[i].PlayerName,
                Coins = newCoins
            };
            return;
        }
    }

}

Can anyone spot where I go wrong ?
Thanks,

Hi there,
I think I have seen this bug crop up in the LeaderboardEntityDisplay script, are you able to share that script?

Hi,
Certainly.

public class LeaderBoardEntityDisplay : MonoBehaviour
{
    [SerializeField] private TMP_Text displayText;
    [SerializeField] private Color myColor = Color.red;


    private FixedString32Bytes playerName;
    public int Coins { get; private set; }
    public ulong ClientId { get; private set; }

    public void Initialise(ulong clientId, FixedString32Bytes playerName, int coins)
    {
        ClientId = clientId;
        this.playerName = playerName;
        Coins = coins;

        if(ClientId == NetworkManager.Singleton.LocalClientId)
        {
            displayText.color = myColor;
        }

        UpdateCoins(0);
    }
    public void UpdateCoins(int coins)
    {
        Coins = coins;
        UpdateText();
    }
    public void UpdateText()
    {
        displayText.text = $"{transform.GetSiblingIndex()+1}. {playerName} ({Coins})";
    }
    

}

Privacy & Terms