Search Unity

SyncListString Not Syncing from Server

Discussion in 'Multiplayer' started by Heckmouse, Nov 13, 2017.

  1. Heckmouse

    Heckmouse

    Joined:
    Nov 7, 2014
    Posts:
    27
    I'm working on a project that uses Unity's Networking features for something relatively simple, maintaining a high score list between a simple game running on multiple machines. I've spent a long time getting this set up, and I feel like I'm close to getting it working, but I've encountered a problem that I just can't seem to figure out.

    I'm using a SyncListString to maintain the list of high scores. Everything works great when I test on one computer, but things start to break down when I connect two computers together. Actually it mostly still works... I'm able to send messages from a client to the host about new high scores to be added to the list, and the host can add them and even save them to a file. But for some reason the SyncListString is always empty on the remote client, and the callback function assigned to the SyncListString never fires. It's worth noting that the client on the host computer works just fine, with a SyncListString that keeps up to date as new high scores are added.

    Has anyone had a similar problem? Could there be some options in the NetworkManager we need to set to get the SyncListString to actually sync between multiple machines?

    Here's the script in it's current state:
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. using System;
    7.  
    8. using UnityEngine.Networking;
    9. using UnityEngine.Networking.NetworkSystem;
    10.  
    11. using System.IO;
    12.  
    13. public class HighScoreList : NetworkBehaviour {
    14.     private const short highScoreMessageCode = 123;
    15.     [SerializeField] SyncListString netHighScores = new SyncListString(); // Shared between clients & server, not human readable
    16.     List<HighScoreEntry> highScores = new List<HighScoreEntry>(); // Use this for UI
    17.     private bool callbackSet = false;
    18.  
    19.     private const short saveHighScoresMessageCode = 234;
    20.     string savePath = "Assets/Resources/highscores.txt";
    21.  
    22.  
    23.     private void Awake()
    24.     {
    25.         DontDestroyOnLoad(transform.gameObject);
    26.     }
    27.  
    28.     // Use this for initialization
    29.     void Start()
    30.     {
    31.         NetworkServer.RegisterHandler(highScoreMessageCode, OnServerPostHighScore);
    32.         NetworkServer.RegisterHandler(saveHighScoresMessageCode, OnServerSaveHighScore);
    33.     }
    34.  
    35.     // Update is called once per frame
    36.     void Update()
    37.     {
    38.  
    39.         if (!callbackSet && NetworkClient.active)
    40.         {
    41.             callbackSet = true;
    42.             netHighScores.Callback = OnHighScoresUpdated;
    43.         }
    44.  
    45.     }
    46.  
    47.     public void AddHighScore(string initials, int score, long birthtime)
    48.     {
    49.         SendHighScore(initials, score, birthtime);
    50.     }
    51.  
    52.     [Client]
    53.     public void SendHighScore(string initials, int score, long birthtime)
    54.     {
    55.        
    56.         StringMessage highScoreMessage = CreateHighScoreMessage(initials, score, birthtime);
    57.         NetworkManager.singleton.client.Send(highScoreMessageCode, highScoreMessage);
    58.     }
    59.  
    60.     [Server]
    61.     void OnServerPostHighScore(NetworkMessage netMsg)
    62.     {
    63.         string message = netMsg.ReadMessage<StringMessage>().value;
    64.  
    65.         if (netHighScores.Count <= 0)
    66.         {
    67.             StreamReader reader = new StreamReader(savePath);
    68.             string savedHighScore = reader.ReadLine();
    69.             while (savedHighScore != null)
    70.             {
    71.                 netHighScores.Add(savedHighScore);
    72.                 savedHighScore = reader.ReadLine();
    73.             }
    74.             reader.Close();
    75.         }
    76.  
    77.         netHighScores.Add(message);
    78.  
    79.         /*
    80.         for (int i = 0; i < netHighScores.Count; i++)
    81.         {
    82.             netHighScores.Dirty(i);
    83.         }
    84.         */
    85.     }
    86.  
    87.     [Client]
    88.     public void SaveHighScores()
    89.     {
    90.        
    91.         StringMessage saveHighScoreMessage = new StringMessage();
    92.         saveHighScoreMessage.value = "dumb";
    93.         NetworkClient _client = NetworkManager.singleton.client;
    94.         _client.Send(saveHighScoresMessageCode, saveHighScoreMessage);
    95.     }
    96.  
    97.     [Server]
    98.     void OnServerSaveHighScore(NetworkMessage netMsg)
    99.     {
    100.         StreamWriter writer = new StreamWriter(savePath, false);
    101.         for (int i = 0; i < netHighScores.Count; i++)
    102.         {
    103.             writer.WriteLine(netHighScores[i]);
    104.         }
    105.         writer.Close();
    106.     }
    107.  
    108.     private void OnHighScoresUpdated(SyncListString.Operation op, int index)
    109.     {
    110.         Debug.Log("list changed: " + op + " at " + index);
    111.         UpdateHighScoreList();
    112.         /*
    113.         for (int i = 0; i < highScores.Count; i++)
    114.         {
    115.             Debug.Log(highScores[i].initials + ": " + highScores[i].birthtime);
    116.         }
    117.         */
    118.     }
    119.  
    120.     public string CreateHighScoreString(string initials, int score, long birthtime)
    121.     {
    122.         string highScoreString = initials + "," + score.ToString() + "," + birthtime.ToString();
    123.         return highScoreString;
    124.     }
    125.  
    126.     public HighScoreEntry DecodeHighScoreString(string highScoreString)
    127.     {
    128.         string[] parts = highScoreString.Split(","[0]);
    129.         int score;
    130.         long birthtime;
    131.         int.TryParse(parts[1], out score);
    132.         long.TryParse(parts[2], out birthtime);
    133.         HighScoreEntry highScore = new HighScoreEntry(parts[0], score, birthtime);
    134.         return highScore;
    135.     }
    136.    
    137.     public StringMessage CreateHighScoreMessage(string initials, int score, long birthtime)
    138.     {
    139.         StringMessage highScoreMessage = new StringMessage();
    140.         highScoreMessage.value = CreateHighScoreString(initials, score, birthtime);
    141.         return highScoreMessage;
    142.     }
    143.  
    144.     public void UpdateHighScoreList()
    145.     {
    146.         highScores = new List<HighScoreEntry>();
    147.  
    148.         Debug.Log("Nethighscore LENGTH YO: " + netHighScores.Count);
    149.  
    150.         for (int i = 0; i < netHighScores.Count; i++)
    151.         {
    152.             highScores.Add(DecodeHighScoreString(netHighScores[i]));
    153.         }
    154.     }
    155.  
    156.     public List<HighScoreEntry> CopyList()
    157.     {
    158.         List<HighScoreEntry> newList = new List<HighScoreEntry>();
    159.  
    160.         for (int i = 0; i < highScores.Count; i++)
    161.         {
    162.             newList.Add(highScores[i]);
    163.         }
    164.  
    165.         return newList;
    166.     }
    167.  
    168.     public List<HighScoreEntry> GetAscendingScores()
    169.     {
    170.         List<HighScoreEntry> ascendingScores = CopyList();
    171.  
    172.         if (ascendingScores.Count > 0)
    173.         {
    174.             ascendingScores.Sort(delegate (HighScoreEntry b, HighScoreEntry a)
    175.             {
    176.                 return (a.score).CompareTo(b.score);
    177.             });
    178.         }
    179.  
    180.         return ascendingScores;
    181.     }
    182.  
    183.     // Returns -1 if the initials and birthtime are not in the highscore list
    184.     public int GetPlayerPosition(string initials, long birthtime, List<HighScoreEntry> highScores)
    185.     {
    186.         int i;
    187.  
    188.         for (i = 0; i < highScores.Count; i++)
    189.         {
    190.             HighScoreEntry highScore = highScores[i];
    191.             if (highScore.initials == initials && highScore.birthtime == birthtime)
    192.             {
    193.                 break;
    194.             }
    195.         }
    196.  
    197.         if (i < highScores.Count)
    198.         {
    199.             return i;
    200.         } else
    201.         {
    202.             return -1;
    203.         }
    204.     }
    205. }