#Unity 3D movement issue

38 messages Β· Page 1 of 1 (latest)

blazing drum
#

I'm have created a simple 3D character movement in unity with state machine, and new input system. I had an issue where the player object move faster while strafing, but move for up, down, left, and right are the same. I already normalized the Vector3 moveDir. How can i fix this?

PlayerStateMachine script :

CharacterController playerControl;
    PlayerInputSystm playerInput;
    PlayerBaseState playerCurrState;
    PlayerStateFactory playerCurrFactory;

    float xDir;
    float zDir;

    public CharacterController PlayerControl { get { return playerControl; } }
    public PlayerBaseState PlayerCurrState { get { return playerCurrState; } set { playerCurrState = value; } }
    public float XDir { get { return xDir; } set { xDir = value; } }
    public float ZDir { get { return zDir; } set { zDir = value; } }

    private void Awake()
    {
        playerControl = GetComponent<CharacterController>();
        playerInput = new PlayerInputSystm();
        playerCurrFactory = new PlayerStateFactory(this);
        playerCurrState = playerCurrFactory.Idle();
        playerCurrState.EnterState();
        playerInput.Player.Movement.performed += OnMove;
        playerInput.Player.Movement.canceled += OnMove;
    }
void Update()
    {
        playerCurrState.UpdateState();
    }

    void OnMove(InputAction.CallbackContext ctx_move)
    {
        xDir = ctx_move.ReadValue<Vector3>().x;
        zDir = ctx_move.ReadValue<Vector3>().z;
    }

    private void OnEnable()
    {
        playerInput.Player.Movement.Enable();
    }

    private void OnDisable()
    {
        playerInput.Player.Movement.Disable();
    }

PlayerIdleState script :

public override void UpdateState()
    {
        CheckSwitchState();
    }
    public override void ExitState()
    {

    }
    public override void CheckSwitchState()
    {
        if(ctx.XDir != 0 || ctx.ZDir != 0)
        {
            SwitchState(factory.Run());
        }
    }
#

PlayerRunState script :

public override void UpdateState()
    {
        CheckSwitchState();
        PlayerMove();
    }
    public override void ExitState()
    {

    }
    public override void CheckSwitchState()
    {
        if(ctx.XDir == 0 || ctx.ZDir == 0)
        {
            SwitchState(factory.Idle());
        }
    }

    void PlayerMove()
    {
        Vector3 moveDir = new Vector3(ctx.XDir, 0, ctx.ZDir).normalized;
        ctx.PlayerControl.Move(moveDir * 3 * Time.deltaTime);
    }
dusty mesa
#

What happens if you log out moveDir.magnitude every frame?

blazing drum
dusty mesa
#

This is weird, it looks right πŸ˜‚ can you show me the move input in your input actions asset?

blazing drum
#

Sure!

#

The input action are like this

#

I'm using the character controller component from unity

dusty mesa
#

Try adding a normalize processor to the input action?

#

Also try changing it to a vector 2 binding instead of vector 3

blazing drum
#

And here's the magnitude
As you can see, when i move using the input action, it's one

dusty mesa
#

Yeah, damn

blazing drum
#

Should i add it in the actions or all the bindings?

dusty mesa
#

The action

blazing drum
#

Still player move faster while strafing πŸ₯²

blazing drum
dusty mesa
#

That just makes sure there's nothing else messing it up

blazing drum
dusty mesa
#

If you do that, you can also export a unity package with just that script + your input action asset, and I'll be able to test on my machine and play around with things for you 😊

blazing drum
#

The script is this :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Player3DMovementScript : MonoBehaviour
{
    CharacterController playerControl;
    PlayerInputSystm playerInput;

    float xDir;
    float zDir;

    private void Awake()
    {
        playerControl = GetComponent<CharacterController>();
        playerInput = new PlayerInputSystm();
        playerInput.Player.Movement.performed += OnMove;
        playerInput.Player.Movement.canceled += OnMove;
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        PlayerMove();
    }

    void PlayerMove()
    {
        Vector3 moveDir = new Vector3(xDir, 0, zDir).normalized;
        playerControl.Move(moveDir * 3 * Time.deltaTime);
    }

    void OnMove(InputAction.CallbackContext ctx_move)
    {
        xDir = ctx_move.ReadValue<Vector2>().x;
        zDir = ctx_move.ReadValue<Vector2>().y;
    }

    private void OnEnable()
    {
        playerInput.Player.Movement.Enable();
    }

    private void OnDisable()
    {
        playerInput.Player.Movement.Disable();
    }
}
#

As you can see
It works fine without the state machine

blazing drum
dusty mesa
blazing drum
#

Owhh i see
Um... so, can i send you the zip of the project?

dusty mesa
#

Sure, it'll be a couple of hours til I get to it though!

blazing drum
#

Ok, i will send the zip of the project

dusty mesa
#

Just the assets folder please!

blazing drum
#

Owhh ok hold on

blazing drum
#

I think i fix it
I just made the player state machine in the update method to update the moveDir, and then check in the idle state if the moveDir is not Vector3.zero

PlayerStateMachine :

void Update()
    {
        playerCurrState.UpdateState();

        onTheGround = Physics.CheckSphere(groundCheck.position, groundCheckRad, groundLayer);
        velocity.y += gravity * Time.deltaTime;

        if(velocity.y < 0 && onTheGround)
        {
            velocity.y = -2f;
        }

        moveDir = new Vector3(xDir, 0, zDir);

        playerControl.Move(velocity * Time.deltaTime);
    }

PlayerIdleState :

public override void CheckSwitchState()
    {
        if(ctx.OnTheGround && ctx.IsJumpPressed)
        {
            SwitchState(factory.Jump());
        }

        if(ctx.MoveDir != Vector3.zero)
        {
            SwitchState(factory.Run());
        }
    }

PlayerRunState :

public override void CheckSwitchState()
    {
        if(ctx.MoveDir == Vector3.zero)
        {
            SwitchState(factory.Idle());
        }
    }

    void PlayerRun()
    {
        ctx.PlayerControl.Move(ctx.MoveDir * 3 * Time.deltaTime);
        ctx.Anim.SetFloat("Speed", 3);

        if (ctx.MoveDir != Vector3.zero)
        {
            ctx.transform.forward = ctx.MoveDir;
        }
    }
#

And it works perfectly

dusty mesa
#

ah I'm glad you fixed it! Sorry I didn't have time to look through the code myself πŸ˜…

blazing drum
#

Chill. Thank you for the help 😁😁