Search Unity

Client sees only default value of SyncListStruct members

Discussion in 'Multiplayer' started by acc_cmwolke, Jul 11, 2018.

  1. acc_cmwolke

    acc_cmwolke

    Joined:
    Aug 29, 2017
    Posts:
    3
    Hi guys!

    I am scratching my head over this one, so maybe you can help out. I have a shared "checklist", which can be modified by the users (both clients and servers). Now, adding the items to the SyncListStruct containing the ChecklistItems works wonderfully - the only issue I have is that the clients are unable to read the individual item's values - they're all default (null / false).

    This is the shared checklist, whose functions are called via command from the client.

    Code (CSharp):
    1. public class SharedChecklistState : NetworkBehaviour {
    2.  
    3. [SyncVar]
    4. public CheckListList Checklist;
    5. [SyncVar]
    6. public float UpdateToken;
    7.  
    8. private static SharedChecklistState instance;
    9. public static SharedChecklistState Instance
    10. {
    11. get
    12. {
    13. return instance;
    14. }
    15. }
    16.  
    17.  
    18. protected virtual void Awake()
    19. {
    20. if (instance != null)
    21. {
    22. Debug.LogErrorFormat("Trying to instantiate a second instance of singleton class {0}", GetType().Name);
    23. }
    24. SharedChecklistState.instance = (SharedChecklistState)this;
    25. }
    26.  
    27. public void AddItem(string text, string GUID)
    28. {
    29. this.Checklist.Add(new ChecklistItem(GUID, text, false));
    30. this.UpdateTimeStamp();
    31. }
    32.  
    33. public void SetItem(bool value, string ID)
    34. {
    35. ChecklistItem item = this.GetItemByID(ID);
    36. if (item.ID != null)
    37. {
    38. int index = this.Checklist.IndexOf(item);
    39. item.done = value;
    40. this.Checklist[index] = item;
    41. }
    42.  
    43. this.UpdateTimeStamp();
    44. }
    45.  
    46. public void RemoveItem(string ID)
    47. {
    48. ChecklistItem item = this.GetItemByID(ID);
    49. if (item.ID != null)
    50. {
    51. this.Checklist.Remove(item);
    52. }
    53. this.UpdateTimeStamp();
    54. }
    55.  
    56. public void UpdateTimeStamp()
    57. {
    58. this.UpdateToken = Time.time;
    59. }
    60.  
    61. private ChecklistItem GetItemByID(string ID)
    62. {
    63. return this.Checklist.First(x => x.ID == ID);
    64. }
    65. }
    66.  
    67. [System.Serializable]
    68. public struct ChecklistItem
    69. {
    70.     public string ID { get; set; }
    71.     public string text { get; set; }
    72.     public bool done { get; set; }
    73.  
    74.     public ChecklistItem(string ID, string text, bool done)
    75.     {
    76.         this.ID = ID;
    77.         this.text = text;
    78.         this.done = done;
    79.     }
    80. }
    81.  
    82. public class CheckListList : SyncListStruct<ChecklistItem> { }
    Client-sided the change is picked up perfectly fine with the changed update token. They then access the checklist via

    foreach (ChecklistItem item in SharedChecklistState.Instance.Checklist) { ... }


    which *does* execute exactly the amount of times there are items in the checklist. But all items (for example when printed out with item.ID / item.text / item.done) are their default values on the client. The server gets the actual values. When adding items client-side, the server still gets the correct value.

    What am I missing?
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
  3. acc_cmwolke

    acc_cmwolke

    Joined:
    Aug 29, 2017
    Posts:
    3
    I did try both and either - having it not as Syncvar and initializing it, still same problem
     
  4. Ellernate

    Ellernate

    Joined:
    Aug 25, 2017
    Posts:
    81
    Just tested this and you're correct this is a bug. SyncListStruct apparently doesn't work with properties, and the unet weaver fails to catch this.

    Simply change your struct to use fields instead and it should work.


    Code (CSharp):
    1. public struct ChecklistItem
    2. {
    3.     public string ID;
    4.     public string text;
    5.     public bool done;
    6.     public ChecklistItem(string ID, string text, bool done)
    7.     {
    8.         this.ID = ID;
    9.         this.text = text;
    10.         this.done = done;
    11.     }
    12. }