TL;DR Clients can control only their player objects with keyboard, but all players with gamepad (using Netcode for Game Objects, Unity Input System and a PS4 Controller)
I am working on a multiplayer game and I am relatively new to multiplayer programming. I am using Netcode for GameObjects.
I am using Unity Input System for handling inputs and I created 2 action maps currently. One for movements (with keyboard and gamepad) and one for attacking (with keyboard, gamepad and mouse).
I am trying to move the players in a Server Authoritative way; thus, I am using Server RPCs for handling movements.
The issue I am having is that, when I play with a Gamepad (PS4 controller), one of the clients can control the others. However, it works perfectly with Keyboard actions.
The code I'm using for the player movement is below:
[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
}
And following is the Action Map I created for movement:
I thought the issue is with the Unity Input System event subscriptions, but I could not find a fix so far for it.
Any help is appreciated!