Проблемы с контроллером игрока UNet

У меня есть контроллер плеера, который должен работать через UNET. Я не должен чего-то понимать, так как любые удаленные игроки, присоединяющиеся к игре, не могут управлять своим персонажем.

Принимающий местный игрок может прекрасно управлять своим персонажем.

В основном, как я думаю, это работает так: в Update локальный игрок может нажимать клавиши. Эти нажатия клавиш выдают Commands на сервер, на котором установлены синхронизированные bools.

В FixedUpdate сервер перемещает Rigidbody на основе установленных bools. На объекте игрока у меня есть NetworkTransform, поэтому любое движение сервера должно быть отправлено обратно клиенту.

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

[RequireComponent(typeof(NetworkIdentity))]
public class PlayerController : NetworkBehaviour {
    public GameObject NormalBullet;

    public Vector3 size = new Vector3(0.25f, 0.25f, 0.25f);
    private float speed = 8;
    private float angularSpeed = 35;
    private float jumpForce = 10;

    private Rigidbody _rigidbody;
    private Map _map;
    private NHNetworkedPool _pool;

    private bool _active = false;
    private Vector3 _lastPosition;

    [SyncVar]
    private bool _moveForward;
    [SyncVar]
    private bool _moveBackward;
    [SyncVar]
    private bool _turnLeft;
    [SyncVar]
    private bool _turnRight;
    [SyncVar]
    private bool _jump;
    [SyncVar]
    private bool _isgrounded;
    [SyncVar]
    private bool _isFireing;

    void Awake () {
        Messenger.AddListener ("MAP_LOADED", OnMapLoaded);

        _rigidbody = gameObject.GetComponent<Rigidbody> ();
        _map = GameObject.Find ("Map").GetComponent<Map> ();

        Physics.IgnoreLayerCollision(LayerMask.NameToLayer("Players"), LayerMask.NameToLayer("Players"), true);
    }

    override public void OnStartClient () {
        _rigidbody.position = new Vector3 (-100, -100, -100);

        if (NetworkServer.active) {
            _pool = FindObjectOfType<NHNetworkedPool> ();
        }
    }

    /// <summary>
    /// Once the board is built, hookup the camera if this is the local player
    /// and set the player as active.
    /// </summary>
    void OnMapLoaded () {
        if (isLocalPlayer) {
            // Hook up the camera
            PlayerCamera cam = Camera.main.GetComponent<PlayerCamera>();
            cam.target = transform;

            // Move the player to the it's spawn location
            CmdSpawn();
        }

        // Set the player as active
        _active = true;
    }

    /// <summary>
    /// Only and active local player should be able to
    /// issue commands for the player
    /// </summary>
    void Update () {
        if (!isLocalPlayer || !_active) {
            return;
        }

        if (Input.GetKeyDown ("up")) {
            CmdSetMoveForward (true);
        }
        if (Input.GetKeyUp ("up")) {
            CmdSetMoveForward (false);
        }
        if (Input.GetKeyDown ("down")) {
            CmdSetMoveBackward (true);
        }
        if (Input.GetKeyUp ("down")) {
            CmdSetMoveBackward (false);
        }
        if (Input.GetKeyDown ("left")) {
            CmdSetTurnLeft (true);
        }
        if (Input.GetKeyUp ("left")) {
            CmdSetTurnLeft (false);
        }
        if (Input.GetKeyDown ("right")) {
            CmdSetTurnRight (true);
        }
        if (Input.GetKeyUp ("right")) {
            CmdSetTurnRight (false);
        }
        if (Input.GetKeyDown (KeyCode.Space)) {
            CmdSetJump (true);
        }
        if (Input.GetKeyUp (KeyCode.Space)) {
            CmdSetJump (false);
        }
        if (Input.GetKeyDown (KeyCode.LeftShift)) {
            CmdSetShooting(true);
        }
        if (Input.GetKeyUp (KeyCode.LeftShift)) {
            CmdSetShooting(false);
        }
    }

    /// <summary>
    /// Only the server should update the player's location
    /// the transform is synced to the clients
    /// </summary>
    void FixedUpdate () {
        if (!isServer) {
            return;
        }

        if (_moveForward) {
            float moveAmount = speed * Time.deltaTime;
            _rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
        }

        if (_moveBackward) {
            float moveAmount = (-speed * 0.6f) * Time.deltaTime;
            _rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
        }

        if (_turnLeft) {
            Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, -angularSpeed, 0f) * Time.deltaTime);
            _rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
        }

        if (_turnRight) {
            Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, angularSpeed, 0f) * Time.deltaTime);
            _rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
        }

        if (_jump && _isgrounded) {
            _rigidbody.AddForce(Vector3.up * 250);
        }
    }

    void OnCollisionStay (Collision collision) {
        if(collision.gameObject.tag.ToUpper() == "GROUND") {
            _isgrounded = true;
        }
    }

    void OnCollisionExit (Collision collision) {
        if(collision.gameObject.tag.ToUpper() == "GROUND") {
            _isgrounded = false;
        }
    }

    /// <summary>
    /// Client -> Server
    /// Move the player to a spawn location
    /// </summary>
    void CmdSpawn() {
        _rigidbody.position = _map.GetPlayerSpawn();
        _rigidbody.velocity = Vector3.zero;
    }

    /// <summary>
    /// Client -> Server
    /// Set the forward move of the player on/off
    /// </summary>
    [Command]
    void CmdSetMoveForward (bool active) {
        _moveForward = active;
    }

    /// <summary>
    /// Client -> Server
    /// Set the backward of the player on/off
    /// </summary>
    [Command]
    void CmdSetMoveBackward (bool active) {
        _moveBackward = active;
    }

    /// <summary>
    /// Client -> Server
    /// Set the left turn of the player on/off
    /// </summary>
    [Command]
    void CmdSetTurnLeft (bool active) {
        _turnLeft = active;
    }

    /// <summary>
    /// Client -> Server
    /// Set the right turn of the player on/off
    /// </summary>
    [Command]
    void CmdSetTurnRight (bool active) {
        _turnRight = active;
    }

    /// <summary>
    /// Client -> Server
    /// Set the jumpping of the player on/off
    /// </summary>
    [Command]
    void CmdSetJump (bool active) {
        _jump = active;
    }

    /// <summary>
    /// Client -> Server
    /// Set shooting weapon on/off
    /// </summary>
    [Command]
    void CmdSetShooting (bool active) {
        _isFireing = true;
    }
}

person Justin808    schedule 10.03.2016    source источник
comment
Вы нашли решение этой проблемы? Я столкнулся с тем же самым.   -  person WajeehHassan    schedule 20.03.2016
comment
@WajeehHassan - еще нет   -  person Justin808    schedule 20.03.2016


Ответы (1)


Вы не должны делать движение по серверу. Перепишите его так, чтобы движение рассчитывалось и выполнялось на клиенте. Затем добавьте к проигрывателю компонент NetworkTransform, и он должен работать.

Только метод Fire должен быть Command. Но поскольку я не знаю, что на самом деле происходит, когда _isFireing = true, я не могу сказать вам, что именно вы должны написать;)

РЕДАКТИРОВАТЬ: Вам также понадобится компонент NetworkIdentity на плеере, если у вас его нет.

person Rafiwui    schedule 11.03.2016
comment
У меня есть NetworkIdentity и у меня NetworkTransform. Я хочу контролировать сервер. Вы не должны доверять клиенту. - person Justin808; 12.03.2016
comment
Другая проблема заключается в том, что [SyncVar] синхронизируется от сервера к клиенту, а не от клиента к серверу (по крайней мере, я так думаю, и это то, что говорит Scripting API) - person Rafiwui; 12.03.2016