【问题标题】:Unity - One client can control all player objects using gamepad (Netcode and Input System)Unity - 一个客户端可以使用游戏手柄(网络代码和输入系统)控制所有玩家对象
【发布时间】:2022-08-15 02:08:33
【问题描述】:

TL;DR 客户端只能使用键盘控制他们的玩家对象,但所有玩家都可以使用游戏手柄(使用游戏对象的网络代码、Unity 输入系统和 PS4 控制器)

我正在开发一款多人游戏,而且我对多人编程还比较陌生。我正在为游戏对象使用网络代码。

我正在使用 Unity 输入系统来处理输入,我目前创建了 2 个动作图。一种用于移动(带有键盘和游戏手柄),一种用于攻击(带有键盘、游戏手柄和鼠标)。

我正在尝试以服务器权威的方式移动玩家;因此,我使用服务器 RPC 来处理动作。

我遇到的问题是,当我使用游戏手柄(PS4 控制器)玩游戏时,其中一个客户端可以控制其他客户端。但是,它与键盘操作完美配合。

我用于玩家移动的代码如下:

[RequireComponent(typeof(Rigidbody))]
public class PlayerMovement : NetworkBehaviour
{
    [SerializeField] private Rigidbody _rb;
    [SerializeField] private float movementSpeed = 10f;
    [SerializeField] private float jumpSpeed = 8f;

    Vector3 _movementVector;

    private PlayerInputActions playerInputActions;

    private PlayerInputActions PlayerInputActions
    {
        get
        {
            if(playerInputActions != null)
            {
                return playerInputActions;
            }
            return playerInputActions = new PlayerInputActions();
        }
    }

    public override void OnNetworkSpawn()
    {
        if(!IsOwner) { return; }
        PlayerInputActions.PlayerMovement.Movement.performed += ctx => SetMovement(ctx.ReadValue<Vector2>());
        PlayerInputActions.PlayerMovement.Movement.canceled += ctx => SetMovement(Vector2.zero);
        PlayerInputActions.PlayerMovement.Jump.performed += PerformJump;
    }

    public override void OnNetworkDespawn()
    {
        if (!IsOwner) { return; }
        PlayerInputActions.PlayerMovement.Movement.performed -= ctx => SetMovement(ctx.ReadValue<Vector2>());
        PlayerInputActions.PlayerMovement.Movement.canceled -= ctx => SetMovement(Vector2.zero);
        PlayerInputActions.PlayerMovement.Jump.performed -= PerformJump;
    }

    private void OnEnable() => PlayerInputActions.Enable();

    private void OnDisable() => PlayerInputActions.Disable();

    private void SetMovement(Vector2 inputVector) => _movementVector = new Vector3(inputVector.x, 0.0f, 0.0f);

    private void PerformJump(InputAction.CallbackContext obj)
    {
        if (!IsOwner) { return; }
        Vector3 jumpVector = Vector3.up;
        HandleJumpServerRpc(jumpVector);
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if(!IsLocalPlayer) { return; }
        HandleMovement();
    }

    private void HandleMovement()
    {
        if (!IsOwner) { return; }
        HandleMovementServerRpc(_movementVector);
    }

    #region Server

    [ServerRpc]
    private void HandleMovementServerRpc(Vector3 movementVector)
    {
        if(Vector3.Distance(movementVector, Vector3.zero) > 0.000001f)
        {
            Debug.Log($\"Owner ID: {OwnerClientId}\");
            _rb.MovePosition(transform.position + movementVector * Time.deltaTime * movementSpeed);
        }
    }

    [ServerRpc]
    private void HandleJumpServerRpc(Vector3 jumpVector)
    {
        if (_rb.velocity.y == 0f)
        {
            _rb.AddForce(jumpVector * jumpSpeed, ForceMode.Impulse);
        }
            
    }

    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log($\"Collided with: {collision.gameObject.name}\");
    }

    #endregion
}

以下是我为运动创建的动作图:

我认为问题出在 Unity Input System 事件订阅上,但到目前为止我找不到解决方法。

任何帮助表示赞赏!

    标签: c# unity3d multiplayer


    【解决方案1】:

    我不确定这是否可行,但我做到了

    public override void OnNetworkSpawn(){
        if (!IsOwner) Destroy(this); 
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-09
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-20
      • 2015-11-20
      • 1970-01-01
      相关资源
      最近更新 更多