如何在统一多人游戏中控制静态对象的动画过渡

时间:2018-09-11 05:06:58

标签: unity3d animation multiplayer unity3d-unet

我想在一个统一多人游戏环境中制作一个静态对象的动画,当玩家单击它时需要发生。动画还会显示连接到服务器的每个玩家

public class AnimationCtr : NetworkBehaviour 
{

    Animator anim;
    bool canSpawn;

    int count;
    [SyncVar]
    bool flag;

    // Use this for initialization
    void Start () 
    {
        anim = GetComponent<Animator>();
        flag = false;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, 100.0f))
            {
                if (hit.transform.gameObject.name.Equals("door") && (!flag))
                {
                    // anim.SetInteger("btnCount", 2);
                    Debug.Log(hit.transform.gameObject.name);
                    anim.SetInteger("btnCount", 2);
                    flag = true; 
                }
                else if (hit.transform.gameObject.name.Equals("door")&& (flag))
                {
                    anim.SetInteger("btnCount", 3);
                    flag = false;
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

一个问题是您不能在客户端设置[Synvar]

来自[SyncVar] docu

  

这些变量的值将从服务器同步到客户端

我也只会让服务器决定flag的当前值是true还是false

public class AnimationCtr : NetworkBehaviour 
{

    Animator anim;
    bool canSpawn;

    int count;
    // no need for sync ar since flag is only needed on the server
    bool flag;

    // Use this for initialization
    void Start () 
    {
        anim = GetComponent<Animator>();
        flag = false;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (!Physics.Raycast(ray, out hit, 100.0f)) return

            if (!hit.transform.gameObject.name.Equals("door")) return;

            // only check if it is a door
            // Let the server handel the rest
            CmdTriggerDoor();
        }
    }

    // Command is called by clients but only executed on the server
    [Command]
    private void CmdTriggerDoor()
    {
        // this will only happen on the Server

        // set the values on the server itself

        // get countValue depending on flag on the server
        var countValue = flag? 3 : 2;
        // set animation on the server
        anim.SetInteger("btnCount", countValue);
        // invert the flag on the server
        flag = !flag;

        //Now send the value to all clients
        // no need to sync the flag as the decicion is made only by server
        RpcSetBtnCount(countValue);
    }

    // ClientRpc is called by the server but executed on all clients
    [ClientRpc]
    private void RpcSetBtnCount(int countValue)
    {
        // This will happen on ALL clients

        // Skip the server since we already did it for him it the Command
        // For the special case if you are host -> server + client at the same time
        if (isServer) return;

        // set the value on the client
        anim.SetInteger("btnCount", countValue);
    }
}

尽管,如果您只想在门打开或关闭时进行动画处理,我宁愿使用bool parameter例如isOpen中的animator,只需对其进行更改(animator.SetBool())。并在两个状态之间有两个转换:

Default -> State_Closed   -- if "isOpen"==true  --> State_Open
                          <-- if "isOpen"==false --

在动画中,只需将1个关键帧保存到目标位置。比过渡时,您可以设置过渡持续时间->门开/关所需的时间(甚至可能不同)。