Mirror/doc/Articles/Guides/Sync/SyncLists.md

107 lines
4.2 KiB
Markdown
Raw Normal View History

2019-07-20 00:05:55 +00:00
# SyncLists
2019-06-25 05:11:37 +00:00
SyncLists are array based lists similar to C\# [List\<T\>](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframework-4.7.2) that synchronize their contents from the server to the clients.
2019-09-21 03:34:03 +00:00
A SyncList can contain any [supported mirror type](../DataTypes.md).
## Differences with HLAPI
2020-10-02 18:56:20 +00:00
HLAPI also supports SyncLists, but we have redesigned them to make them more efficient and easier to use. Some of the key differences include:
2019-06-25 05:11:37 +00:00
- In HLAPI, SyncLists were synchronized immediately when they changed. If you add 10 elements, that means 10 separate messages. Mirror synchronizes SyncLists with the SyncVars. The 10 elements and other SyncVars are batched together into a single message. Mirror also respects the sync interval when synchronizing lists.
- In HLAPI if you want a list of structs, you have to use `SyncListStruct<MyStructure>`, we changed it to just `SyncList<MyStructure>`
- In HLAPI the Callback is a delegate. In Mirror we changed it to an event, so that you can add many subscribers.
- In HLAPI the Callback tells you the operation and index. In Mirror, the callback also receives an item. We made this change so that we could tell what item was removed.
2020-10-02 18:56:20 +00:00
- In HLAPI you must create a class that inherits from SyncList<T>. In Mirror you can just use SyncList<T> directly (starting with version 20.0.0)
## Usage
2020-10-02 18:56:20 +00:00
Add a SyncList field to your NetworkBehaviour class. For example:
2019-07-07 05:52:37 +00:00
```cs
2019-03-20 11:47:50 +00:00
public struct Item
{
2019-03-20 11:47:50 +00:00
public string name;
public int amount;
public Color32 color;
}
2020-01-15 00:23:46 +00:00
public class Player : NetworkBehaviour
2019-08-10 23:09:18 +00:00
{
2020-10-02 18:56:20 +00:00
readonly SyncList<Item> inventory = new SyncList<Item>();
2019-03-20 11:47:50 +00:00
public int coins = 100;
[Command]
public void CmdPurchase(string itemName)
{
if (coins > 10)
{
coins -= 10;
2019-09-26 00:12:59 +00:00
Item item = new Item
2019-03-20 11:47:50 +00:00
{
name = "Sword",
amount = 3,
2019-09-26 00:12:59 +00:00
color = new Color32(125, 125, 125, 255)
2019-03-20 11:47:50 +00:00
};
// during next synchronization, all clients will see the item
2019-09-26 00:12:59 +00:00
inventory.Add(item);
2019-03-20 11:47:50 +00:00
}
}
}
2019-03-20 11:47:50 +00:00
```
2019-08-19 21:48:38 +00:00
You can also detect when a SyncList changes in the client or server. This is useful for refreshing your character when you add equipment or determining when you need to update your database. Subscribe to the Callback event typically during `Start`, `OnClientStart`, or `OnServerStart` for that.
2019-08-20 13:29:55 +00:00
> Note that by the time you subscribe, the list will already be initialized, so you will not get a call for the initial data, only updates.</p>
> Note SyncLists must be initialized in the constructor, not in Startxxx(). You can make them readonly to ensure correct usage.
2019-03-20 11:47:50 +00:00
2019-07-07 05:52:37 +00:00
```cs
2019-03-20 11:47:50 +00:00
class Player : NetworkBehaviour {
2020-10-02 18:56:20 +00:00
readonly SyncList<Item> inventory = new SyncList<Item>();
2019-03-20 11:47:50 +00:00
// this will add the delegates on both server and client.
// Use OnStartClient instead if you just want the client to act upon updates
void Start()
{
inventory.Callback += OnInventoryUpdated;
2019-03-20 11:47:50 +00:00
}
2020-10-02 18:56:20 +00:00
void OnInventoryUpdated(SyncList<Item>.Operation op, int index, Item oldItem, Item newItem)
2019-03-20 11:47:50 +00:00
{
switch (op)
2019-03-20 11:47:50 +00:00
{
2020-10-02 18:56:20 +00:00
case SyncList<Item>.Operation.OP_ADD:
2019-03-20 11:47:50 +00:00
// index is where it got added in the list
// item is the new item
break;
2020-10-02 18:56:20 +00:00
case SyncList<Item>.Operation.OP_CLEAR:
2019-03-20 11:47:50 +00:00
// list got cleared
break;
2020-10-02 18:56:20 +00:00
case SyncList<Item>.Operation.OP_INSERT:
2019-03-20 11:47:50 +00:00
// index is where it got added in the list
// item is the new item
break;
2020-10-02 18:56:20 +00:00
case SyncList<Item>.Operation.OP_REMOVEAT:
2019-03-20 11:47:50 +00:00
// index is where it got removed in the list
// item is the item that was removed
break;
2020-10-02 18:56:20 +00:00
case SyncList<Item>.Operation.OP_SET:
2019-03-20 11:47:50 +00:00
// index is the index of the item that was updated
// item is the previous item
break;
}
}
}
```
2020-10-02 18:56:20 +00:00
By default, SyncList uses a List to store it's data. If you want to use a different list implementation, pass it to the constructor of of SyncList. For example:
2019-07-07 05:52:37 +00:00
```cs
2020-10-02 18:56:20 +00:00
class Player : NetworkBehaviour {
public SyncList<Item> inventory = new SyncList<Item>(new MyItemList());
}
```