首页 > 解决方案 > 未调用 Unity3D 的客户端命令

问题描述

所以客户端上没有调用玩家移动命令(主机很好)。正在调用循环,我检查它是否仅在本地播放器上。但是没有调用实际的命令。该脚本位于在网络管理器中注册的播放器预制件上。我究竟做错了什么?

using UnityEngine;
using UnityEngine.Networking;

public class MovePlayer : NetworkBehaviour {
    float speed;
    Rigidbody2D rigidbody;
    Player player;
    int verticalDir = 0;
    float rot_z;
    int horizontalDir = 0;

    void Start () {
        player = gameObject.GetComponent<Player>();
        rigidbody = gameObject.GetComponent<Rigidbody2D>();
        speed = player.moveSpeed;
    }

    void Update () {
        if (!player.dead && isLocalPlayer)
        {
            // Key Movement
            verticalDir = 0;
            horizontalDir = 0;
            if (Input.GetKey("w"))
            {
                verticalDir += 1;
            }
            if (Input.GetKey("s"))
            {
                verticalDir -= 1;
            }
            if (Input.GetKey("a"))
            {
                horizontalDir -= 1;
            }
            if (Input.GetKey("d"))
            {
                horizontalDir += 1;
            }

            // Mouse Tracking
            Vector3 diff = player.camera.ScreenToWorldPoint(Input.mousePosition) - transform.position;
            diff.Normalize();

            rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
            CmdMove();

            // Velocity limit
            if (rigidbody.velocity.x > speed)
            {
                rigidbody.velocity = new Vector2(speed, rigidbody.velocity.y);
            }
            if (rigidbody.velocity.y > speed)
            {
                rigidbody.velocity = new Vector2(rigidbody.velocity.x, speed);
            }
        }
    }
    [Command]
    void CmdMove()
    {
        var locVel = new Vector2(speed * horizontalDir, speed * verticalDir);
        rigidbody.velocity = locVel;
        gameObject.transform.rotation = Quaternion.Euler(0f, 0f, rot_z - 90);
    }
}

标签: c#unity3d

解决方案


你在使用/想command错了!我将尝试简短地解释一下:

  • A[Command]由客户端调用,但在服务器上执行!
  • A[ClientRpc]由服务器调用,但由所有客户端执行
  • A[Client]只是确保此方法只能由客户端执行

现在来看一个代码示例:

// This is called by the client
[Client]
private void DoSomething()
{
    if(!isLocalPlayer) return;

    // Here we call the command on the server passing our gameObject
    CmdDoSomething(gameObject);
}

// This is only executed on the server
// Since the player has a NetworkIdentity the server can identify the correct gameObject we passed
[Command]
private void CmdDoSomething (GameObject player)
{
    // Do stuff that happens only on the server here


    // Now we can send back Information
    // E.g. an int or string again passing the GameObject
    RpcDoSomething(player, "test");
}

// Usually this would be executed by ALL clients
// So we have to check if we are the player who originally called the command
// Again the NetworkIdentity makes sure we can identify the passed GameObject
[ClientRpc]
private void RpcDoSomething (GameObject player, string message)
{
    // For the special case that we are the host (server and client at the same time)
    // we maybe don't want to do something
    // since we probably already did it for ourself before while executing the [Command]
    if(isServer) return;

    // If we are not the one who invoked the command we do nothing
    if(player != gameObject) return;

    // I like to put Debug.Log containing "this" in the end so you can click a Log
    // Entry and see exactly where it came from
    Debug.Log("I received: " + message, this);
}

从这里您现在应该能够根据您的需要实施它。


推荐阅读