Need help with character movement code

Hi all!

So, the below code can move my character in all directions and it can rotate it towards the direction that it’s moving. For example, if I press S + A, the character will turn around to face the camera and walks back (facing backward) diagonally towards the Left. But what I want is to prevent the character from turning around when I hit S (or S + A / S + D), and just move backwards while facing Forwards. Can you guys please suggest how to do that?
I have images uploaded.
Hope I’m making sense.

float move = Input.GetAxis("Vertical");
        if (move > 0)
        {
            anim.SetInteger("Move", 1); // walk forward anim
        }else if(move < 0)
        {
            anim.SetInteger("Move", -1); // walk back anim
        }
        else if(move == 0)
        {
            anim.SetInteger("Move", 0); // idle anim
        }

        float horizontalMove = Input.GetAxisRaw("Horizontal"); // A = -1, D = +1
        float verticalMove = Input.GetAxisRaw("Vertical"); // W = +1, S = -1
        Vector3 MoveDirection = new Vector3(horizontalMove, 0f, verticalMove).normalized; // Direction to move in X and Z directions. Normalized to fix the diagonal movement discrepancy
       
        if(MoveDirection.magnitude >= 0.1f) // If there's an input for moving
        {
            float targetAngle = Mathf.Atan2(MoveDirection.x, MoveDirection.z) * Mathf.Rad2Deg + Cam.eulerAngles.y; // Get the Angle to Rotate (including the Cam angle)
            float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime); // Smoothes the rotation from current angle to targetAngle

            transform.rotation = Quaternion.Euler(0f, angle, 0f); // Rotate on Y

            Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward; // Convert the angle into a direction, for moving
            controller.Move(moveDir.normalized * speed * Time.deltaTime); // Move in the desired direction with the speed
        }

Thanks for any input!


Maybe just wrap the rotation part in an if statement like this?

if (verticalMove >= 0) {
  transform.rotation = Quaternion.Euler(0f, angle, 0f); // Rotate on
}

If you can give the player input anywhere around the compass (all headings from 0 to 360), then one way is to compare which way the player is facing now (heading) with which way you are attempting to tell him to move, then deciding if the shorter way is “back” or “forward.”

Here’s a snippet in isolation from my (yet unpublished) Tanks Of Kurt game that sorta shows the steps:

    void UpdateMoving ( bool fingerDown, Vector3 output)
    {
        float DesiredSpeed = 0;

        if (fingerDown &&
            (output.sqrMagnitude != 0))
        {
            DesiredSpeed = output.magnitude * MaxPlayerSpeed;

/// which direction are we asking to move?
            CommandFacing = Mathf.Atan2( output.x, output.y) * Mathf.Rad2Deg;

// offset it by the camera so it is always camera relative
            CommandFacing += CameraFacing;

// how different is it from the current tank heading?
            float delta = Mathf.DeltaAngle(BodyFacing, CommandFacing);

// oop, looks like it's different enough we should move backwards instead of forward
            if ((delta < -90) || (delta > 90))
            {
                CommandFacing += 180.0f;
                DesiredSpeed = -DesiredSpeed;
            }

// how much do we turn this frame
            float DegreesThisFrame = BodyRotationSpeed * Time.deltaTime;
            BodyFacing = Mathf.MoveTowardsAngle(
                BodyFacing, CommandFacing, DegreesThisFrame);

// and now produce the rotation to use
            Quaternion Q = Quaternion.Euler( 0, BodyFacing, 0);
            /// use Q to set the rotation
        }

Games that use this sort of motion:

  • Battletanx N64
  • Halo on the marines 4-wheel-drive gun truck
  • Mass Effect six wheeled lander craft

And I’m sure many more.