1

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: Action Map

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!

2 Answers 2

1

Are you still having this issue? Because i think this has to due with the input system. Basically if you use C# events your schemes will be ignored and you will control both characters.

I just posted a question waiting for some clarification, you can overcome that problem by using Invoke unity events in the PlayerInput behaviour

PlayerInput component

Anyway, here's my question if you're interested, it seems a bit weird that 4 years later this simple thing is not fixed...

Unity Input system C# events still not working after 4 years?

1
  • Hey thanks for the response! I ended up abandoning the project as I lost my motivation after spending so much time on this issue. I am still interested in the fix though. Thus, I will check your solution as soon as possible. Thanks again :)
    – brsdncr
    Commented May 3, 2024 at 12:55
0

I'm not sure if this will work but I did

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.