1

我有一个可以在 UNET 上工作的播放器控制器。我一定不明白,因为任何远程玩家加入游戏都无法控制他们的角色。

托管本地玩家可以很好地控制他/她的角色。

基本上我认为这是可行的方式是在Update本地播放器中可以按键。这些按键Command向设置同步布尔值的服务器发出 s。

FixedUpdate服务器中,根据设置的布尔值移动刚体。在播放器对象上,我有一个 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;
    }
}
4

1 回答 1

0

您不应该在服务器上进行移动。重写它,以便在客户端计算和执行移动。然后向播放器添加一个 NetworkTransform 组件,它应该可以工作。

只有 Fire 方法必须是Command. _isFireing = true但是因为当我不能告诉你你应该写什么时,我不知道实际发生了什么;)

编辑:如果您没有播放器,您还需要一个 NetworkIdentity 组件

于 2016-03-11T21:12:57.860 回答