Search Unity

Can't figure out how to use SyncListStruct

Discussion in 'Multiplayer' started by KungFooMasta, Oct 15, 2016.

  1. KungFooMasta

    KungFooMasta

    Joined:
    May 27, 2014
    Posts:
    24
    I've been searching around and looking at other people who have got it working, but I can't figure out what is wrong in my scenario. My game has multiple characters with belts, and I want the server instances to manage the belt configuration and sync that to clients.

    Declaration of my SyncListStruct type:
    Code (CSharp):
    1.     public struct BeltItemSyncData
    2.     {
    3.         public int ItemID;
    4.         public int Quantity;
    5.         public float Cooldown;
    6.  
    7.         public BeltItemSyncData(BeltSlotMeta beltSlotMeta)
    8.         {
    9.             this.ItemID = (int)beltSlotMeta.ItemID;
    10.             this.Quantity = beltSlotMeta.Quantity;
    11.             this.Cooldown = 0;
    12.         }
    13.  
    14.         public BeltItemSyncData(int itemID, int quantity, float cooldown)
    15.         {
    16.             this.ItemID = itemID;
    17.             this.Quantity = quantity;
    18.             this.Cooldown = cooldown;
    19.         }
    20.     }
    21.  
    22.     public class SyncList_BeltItems : SyncListStruct<BeltItemSyncData> {}
    Instantiation of the SyncList_BeltItems type in my Character class:
    Code (CSharp):
    1.     [RequireComponent(typeof(NetworkTransform))]
    2.     [RequireComponent(typeof(CharacterController))]
    3.     public class CharacterInstance : CharacterControllerManager, ICollidable
    4.     {
    5.         ...
    6.  
    7.         public SyncList_BeltItems BeltItems = new SyncList_BeltItems();
    8.  
    9.         ...
    10.  
    11.         // Use this for initialization
    12.         public override void Start()
    13.         {
    14.             base.Start();
    15.  
    16.             BeltItems.Callback = OnBeltItemsChanged_Internal;
    17.             ...
    18.         }
    19.  
    20.         protected virtual void OnBeltItemsChanged(SyncListStruct<BeltItemSyncData>.Operation operation, int index)
    21.         {
    22.             //BeltItemSyncData beltItem = BeltItems[index];
    23.             //ItemID itemID = (ItemID)beltItem.ItemID;
    24.  
    25.             switch (operation)
    26.             {
    27.                 case SyncList<BeltItemSyncData>.Operation.OP_DIRTY: // An item property changed
    28.                     Log.Add("PlayerInstance.OnBeltItemsChanged(): An item property changed");
    29.                     break;
    30.                 case SyncList<BeltItemSyncData>.Operation.OP_SET: // An item has been replaced by another
    31.                     Log.Add("PlayerInstance.OnBeltItemsChanged(): An item has been replaced by another");
    32.                     break;
    33.                 default:
    34.                     Log.Add("PlayerInstance.OnBeltItemsChanged(): Unsupported SyncListStruct<BeltItemSyncData> Operation: {0}", operation.ToString());
    35.                     break;
    36.             }
    37.         }
    38.  
    39.         private void OnBeltItemsChanged_Internal(SyncListStruct<BeltItemSyncData>.Operation operation, int index)
    40.         {
    41.             OnBeltItemsChanged(operation, index);        
    42.         }
    And when I walk over an item on the ground, I update the belt (on the server), but I don't get any kind of output telling me the belt has been updated on the client. (OnBeltItemsChanged)

    Code (CSharp):
    1.         public void OnItemTouched(ItemInstance itemInstance)
    2.         {
    3.             // Only the server instance of the character can pick up items.
    4.             if (!isServer)
    5.             {
    6.                 return;
    7.             }
    8.  
    9.             ItemMeta itemMeta = ItemManager.Instance.GetItemMeta(itemInstance.ItemID);
    10.  
    11.             // Do we have room?
    12.             int slotIndex = GetSlotIndexForItem(itemMeta);
    13.             if (slotIndex != -1)
    14.             {
    15.                 BeltItemSyncData oldItem = BeltItems[slotIndex];
    16.                 BeltItemSyncData newItem = new BeltItemSyncData(oldItem.ItemID, oldItem.Quantity + 1, oldItem.Cooldown);
    17.                 BeltItems[slotIndex] = newItem;
    18.  
    19.                 NetworkServer.Destroy(itemInstance.gameObject);
    20.             }
    Sorry for posting large amounts of code, hopefully its not too hard to walk through. Any idea what I'm doing wrong? The item is being destroyed so I know this code is being executed on the server, but updating my sync list struct doesn't call OnBeltItemsChanged_Internal.