Unet 同步动画图层权重 Unity 3D

Unet Syncing animator layer weight Unity 3D

我目前正在研究多人 fps 以学习 UNET 和 Unity。在这个项目中,我使用 Network Animator Component 来同步我的动画。
我有一层运行正常状态,如行走和跳跃,另一层仅控制上半身以进行范围界定。该层在确定范围时被激活。

参数同步正常但层权重不同步。 控制图层权重的脚本在远程播放器上被禁用,因为它是负责拍摄的同一脚本的一部分,我们不想从远程播放器拍摄。 所以我将该代码放在不同的脚本上并将 Layerweight 设为 Syncvar,但仍然没有结果。

这是设置权重并将其淡出的片段。

    if (isScoped)
    {
        animator.SetLayerWeight(1, 1);
        layerWeight = 1;
    }
    else
    {
        layerWeight = Mathf.Lerp(layerWeight, 0, 0.1f);
        animator.SetLayerWeight(1, layerWeight);
    }

    animator.SetBool("Scoped", isScoped);

如何同步在禁用脚本上更新的变量? 我应该使用哪些不同的自定义属性(例如 [Command] 和 [ClientRpc])来使其正常工作?
我已经阅读了 UNET 的文档和手册,但由于我很难理解这些调用的区别,所以很难完成这项相对简单的任务。

总的来说,[SyncVar] 的主要问题是它们

synchronized from the server to clients

所以不是反过来!


然后

[Command] 是一种 被任何客户端 调用但仅在 服务器上执行

的方法

[ClientRpc]有点相反,它是由服务器调用,然后在所有客户端

所以我要做的是为图层权重设置一个setter方法,比如

private void SetLayerWeight(float value)
{
    // only player with authority may do so
    if(!isLocalPlayer) return;

    // Tell the server to update the value
    CmdSetLayerWeight(value);
}

[Command]
private void CmdSetLayerWeight(float value)
{
    // Server may now tell it to all clients
    RpcSetLayerWeight(value);
}

[ClientRpc]
private void RpcSetLayerWeight(float value)
{
    // called on all clients including server
    layerweight = value;
    animator.SetLayerWeight(1, layerweight);
}

并这样称呼它

if (isScoped)
{
    SetLayerWeight(1);
}
else
{
    SetLayerWeight(Mathf.Lerp(layerWeight, 0, 0.1f));
}

请注意,在服务器和客户端之间来回传递此信息会导致一些不可思议的延迟!

您最好同步 isScoped 布尔值并直接在调用客户端上分配值:

private void SetScoped(bool value)
{
    // only player with authority may do so
    if(!isLocalPlayer) return;

    // for yourself already apply the value directly so you don't have
    // to wait until it comes back from the server
    scoped = value;

    // Tell the server to update the value and who you are
    CmdSetLayerWeight(value);
}

// Executed only on the server
[Command]
private void CmdSetLayerWeight(bool value)
{
    // Server may now tell it to all clients
    RpcSetLayerWeight(value);
}

// Executed on all clients
[ClientRpc]
private void RpcSetLayerWeight(bool value)
{
    // called on all clients including server
    // since setting a bool is not expensive it doesn't matter
    // if this is done again also on the client who originally initialized this
    scoped = value;
}