英文原文:
https://mirror-networking.gitbook.io/docs/guides/synchronization/synclists
SyncList 是类似于 C# List 的基于数组的列表,可将其内容从服务器同步到客户端。
SyncList 可以包含任何受支持的镜像类型。
与 UNET 的区别
UNET 也支持 SyncLists,但我们重新设计了它们以使其更高效且更易于使用。一些主要区别包括:
-
在 UNET 中,SyncList 在更改时会立即同步。如果添加 10 个元素,则意味着 10 个单独的消息。 Mirror 将 SyncLists 与 SyncVars 同步。这 10 个元素和其他 SyncVar 一起批处理为一条消息。同步列表时,Mirror 也遵守同步间隔。
-
在 UNET 中,如果您想要一个结构列表,则必须使用 SyncListStruct,我们将其更改为仅 SyncList
-
在 UNET 中,回调是一个委托。在 Mirror 中,我们将其更改为一个事件,以便您可以添加许多订阅者。
-
在 UNET 中,回调告诉您操作和索引。在 Mirror 中,回调也接收一个item。我们进行了此更改,以便我们可以知道删除了哪些item。
-
在 UNET 中,您必须创建一个继承自 SyncList 的类。在 Mirror 中,您可以直接使用 SyncList(从 20.0.0 版本开始)
使用方法
将 SyncList 字段添加到您的 NetworkBehaviour 类。
SyncList 必须声明为只读并在构造函数中初始化。
public struct Item
{
public string name;
public int amount;
public Color32 color;
}
public class Player : NetworkBehaviour
{
public readonly SyncList<Item> inventory = new SyncList<Item>();
public int coins = 100;
[Command]
public void CmdPurchase(string itemName)
{
if (coins > 10)
{
coins -= 10;
Item item = new Item
{
name = "Sword",
amount = 3,
color = new Color32(125, 125, 125, 255)
};
// 在下一次同步期间,所有客户端都将看到该item
inventory.Add(item);
}
}
}
您还可以检测客户端或服务器中 SyncList 何时更改。这对于在添加设备或确定何时需要更新数据库时刷新角色很有用。为此,通常在 Start、OnClientStart 或 OnServerStart 期间订阅 Callback 事件。
请注意,当您订阅时,该列表已经被填充,因此您不会收到初始数据的调用,只会更新。
class Player : NetworkBehaviour {
public override void OnStartClient()
{
inventory.Callback += OnInventoryUpdated;
// 处理初始 SyncList 有效负载
for (int index = 0; index < inventory.Count; index++)
OnInventoryUpdated(SyncList<Item>.Operation.OP_ADD, index, new Item(), inventory[index]);
}
void OnInventoryUpdated(SyncList<Item>.Operation op, int index, Item oldItem, Item newItem)
{
switch (op)
{
case SyncList<Item>.Operation.OP_ADD:
// index 是它被添加到列表中的位置
// newItem 是新item
break;
case SyncList<Item>.Operation.OP_INSERT:
//index 是它被插入到列表中的位置
// newItem 是新item
break;
case SyncList<Item>.Operation.OP_REMOVEAT:
// index 是从列表中删除的位置
// oldItem 是被移除的item
break;
case SyncList<Item>.Operation.OP_SET:
// 索引是已更改的项目
// oldItem 是索引处item的先前值
// newItem 是索引处item的新值
break;
case SyncList<Item>.Operation.OP_CLEAR:
// list被清除
break;
}
}
}