(004)Mirror 变量的同步

支持的同步数据类型

1.数据状态的同步方向是 Server to Client。 支持的数据类型分别是:

Client to Server 的同步需要使用 Command

2.声明了同步变量的脚本类需要继承 NetworkBehaviour。同一个物体(NetworkIdentity标记)可以同时挂载多个 NetworkBehaviour 脚本。

3.NetworkBehaviour 的子类的同步变量支持继承

4.单个 NetworkBehaviour 的同步变量的 dirty 标志位用 ulong 表示,因此单个脚本能支持最多 64个同步变量。

在这里插入图片描述

如果多层继承的话,已声明的sync变量数量也应该包括被继承类声明的 sync变量。

同步的目标

1.通常同步变量变化的时候,所有客户端都能接收到广播通知。但是有些情况是只需要向变量的拥有者同步的,比如玩家的背包数据,从安全性能考虑,这个时候只需要向背包的拥有者同步就可以了。

Sync ModeObservers 改为 Ower
在这里插入图片描述

自定义同步行为

1.Mirror 提供了定制同步行为的能力,这是通过修改序列化反序列化同步数据的行为实现的。

public virtual bool OnSerialize(NetworkWriter writer, bool initialState);
public virtual void OnDeserialize(NetworkReader reader, bool initialState);

同步分为全量同步行为和增量同步行为。initialStatetrue 的时候,属于全量同步;否则,
序列化反序列化 只需要包含变化的数据就可以了。

OnSerialize 只有在 Sync 变量变化的时候,才会被调用。调用的间隔由 Sync Interval决定。

在这里插入图片描述

序列化和反序列化的细节

1.服务器端调用 OnSerialize 简化示意图:

SetDirtyBit
UpdateVars
ClearDirtyBit
broadcastUpdateVars

----- 服务器端调用 OnDeSerialize 简化示意图:

ReceiveUpdateVars
OnDeserialize
SyncVarHook

2.比如下面的脚本拥有同步变量:

public class data : NetworkBehaviour
{
    [SyncVar(hook = nameof(OnInt1Changed))]
    public int int1 = 66;

    [SyncVar]
    public int int2 = 23487;

    [SyncVar]
    public string MyString = "Example string";

    void OnInt1Changed(int oldValue, int newValue)
    {
        // do something here
    }
}

— 序列化过程:

public override bool SerializeSyncVars(NetworkWriter writer, bool initialState)
{
    // Write any SyncVars in base class
    bool written = base.SerializeSyncVars(writer, forceAll);

    if (initialState)
    {
        // The first time a game object is sent to a client, send all the data (and no dirty bits)
        writer.WritePackedUInt32((uint)this.int1);
        writer.WritePackedUInt32((uint)this.int2);
        writer.Write(this.MyString);
        return true;
    }
    else 
    {
        // Writes which SyncVars have changed
        writer.WritePackedUInt64(base.syncVarDirtyBits);

        if ((base.get_syncVarDirtyBits() & 1u) != 0u)
        {
            writer.WritePackedUInt32((uint)this.int1);
            written = true;
        }

        if ((base.get_syncVarDirtyBits() & 2u) != 0u)
        {
            writer.WritePackedUInt32((uint)this.int2);
            written = true;  
        }

        if ((base.get_syncVarDirtyBits() & 4u) != 0u)
        {
            writer.Write(this.MyString);
            written = true;     
        }

        return written;
    }
}

— 反序列化过程:

public override void DeserializeSyncVars(NetworkReader reader, bool initialState)
{
    // Read any SyncVars in base class
    base.DeserializeSyncVars(reader, initialState);

    if (initialState)
    {
        // The first time a game object is sent to a client, read all the data (and no dirty bits)
        int oldInt1 = this.int1;
        this.int1 = (int)reader.ReadPackedUInt32();
        // if old and new values are not equal, call hook
        if (!base.SyncVarEqual(num, ref this.int1))
        {
            this.OnInt1Changed(num, this.int1);
        }

        this.int2 = (int)reader.ReadPackedUInt32();
        this.MyString = reader.ReadString();
        return;
    }

    int dirtySyncVars = (int)reader.ReadPackedUInt32();
    // is 1st SyncVar dirty
    if ((dirtySyncVars & 1) != 0)
    {
        int oldInt1 = this.int1;
        this.int1 = (int)reader.ReadPackedUInt32();
        // if old and new values are not equal, call hook
        if (!base.SyncVarEqual(num, ref this.int1))
        {
            this.OnInt1Changed(num, this.int1);
        }
    }

    // is 2nd SyncVar dirty
    if ((dirtySyncVars & 2) != 0)
    {
        this.int2 = (int)reader.ReadPackedUInt32();
    }

    // is 3rd SyncVar dirty
    if ((dirtySyncVars & 4) != 0)
    {
        this.MyString = reader.ReadString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值