Top down wasd movement dependent on rotation of the character - Mathematical problem!!!

Hey there,

I’m programming a top down view game with with wasd movement controlls.
I want my character to move by 3.741f * Time.deltaTime in the direction in which he Looks. (Maybe incorrect grammar ^^ )

To achieve this I want to use the law of sine.
First of all the Code:

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{ 
	private Animator anim;
	private bool left, right, forward, backward;
    private float angle_to_rotate = 90, movementInput = 0.0f;

    //movement
    private int switchValue, xBehavior, zBehavior;
    private float deltaX, deltaZ;
    private float alpha, beta, gamma = 90;

    public Input_m EventSystem;

	void Awake () {
		anim = GetComponent<Animator> ();
	}
	
	// Update is called once per frame
	void Update () {
		left = EventSystem.Pressed("Left");
		right = EventSystem.Pressed("Right");
        forward = EventSystem.Pressed("Forward");
        backward = EventSystem.Pressed("Backward");

        SetAnimationStats();
        Rotate();
    }

    private void FixedUpdate()
    {
        Move();
    }

    void CalculateAngle () {
		if (left && !right && !forward && !backward)
			angle_to_rotate = 225;
        else if (left && !right && forward && !backward)
            angle_to_rotate = 270;
        else if (!left && !right && forward && !backward)
            angle_to_rotate = 315;
        else if (!left && right && forward && !backward)
            angle_to_rotate = 360;
        else if (!left && right && !forward && !backward)
			angle_to_rotate = 45;
        else if (!left && right && !forward && backward)
            angle_to_rotate = 90;
        else if (!left && !right && !forward && backward)
            angle_to_rotate = 135;
        else if (left && !right && !forward && backward)
            angle_to_rotate = 180;
    }

    private void Rotate()
    {
        CalculateAngle();
        transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(transform.rotation.eulerAngles.x, angle_to_rotate, transform.rotation.eulerAngles.z), 0.125f);
    }

    private void SetAnimationStats()
    {        
        if ((left && !right && (!backward || !forward)) || (!left && ((!right && ((!forward && backward) || (forward && !backward))) || (right && (!backward || !forward)))))
        { 
            movementInput += Time.deltaTime * 3;
            movementInput = Mathf.Min(movementInput, 1.0f);
        }
        else
        {
            movementInput -= Time.deltaTime * 3;
            movementInput = Mathf.Max(movementInput, 0.0f);
        }

        anim.SetFloat("movementInput", movementInput);
    }

    private void Move()
    {
        if ((left && !right && (!backward || !forward)) || (!left && ((!right && ((!forward && backward) || (forward && !backward))) || (right && (!backward || !forward)))))
        {
            alpha = transform.rotation.eulerAngles.y % 90;
            beta = 180 - alpha - gamma;
            switchValue = (int)(transform.rotation.eulerAngles.y / 90);

            switch (switchValue)
            {
                case 0:
                    xBehavior = 1;
                    zBehavior = 1;
                    break;
                case 1:
                    xBehavior = 1;
                    zBehavior = -1;
                    break;
                case 2:
                    xBehavior = -1;
                    zBehavior = -1;
                    break;
                case 3:
                    xBehavior = -1;
                    zBehavior = 1;
                    break;
                case 4:
                    xBehavior = 1;
                    zBehavior = 1;
                    break;
                default:
                    break;
            }

            deltaX = 1.0f * Mathf.Sin(beta) / Mathf.Sin(gamma);
            deltaZ = 1.0f * Mathf.Sin(alpha) / Mathf.Sin(gamma);

            Debug.Log(deltaX.ToString() + " ; " + deltaZ.ToString());

            transform.position = new Vector3(transform.position.x + 3.741f * Time.deltaTime * deltaX * xBehavior, transform.position.y, transform.position.z + 3.741f * Time.deltaTime * deltaZ * zBehavior);
        }
    }
}

First of all the strategy. Because I move on the X and the Z axis I divide the rotations into 4 parts. 0 - 89.9999, 90 - 179.9999, 180 - 269.9999 and 270 - 359.9999 degrees.

I use the modulus to find out in which quadrant the values ​​are located so that I negate the X or Z values ​​if necessary.

The rest of the division is then always an angle between 0 and 90 degrees.

Then I use the law of sinus to calculate the X and Z values ​​for the movement so that the length of the third side of the triangle is exactly 1.

the final values ​​are then multiplied by these calculated values.

But this does not work. the character is not moving in the direction but rather wildly zapped

Looking Forward for a Reply :slight_smile:

P.S. Don’t care about the if Statements with all the left - right - Forward - backward. These are transformed using the Boolean algebra and correct.

There are a lot things wrong and / or confusing.

Lets start with the obvious ones: All trigonometric functions inside Mathf that expect or return angles use radians and not degree. However you pass angles in degree. So the result is pretty non-sense.

You read back transform.rotation.eulerAngles.y and turn it into an integer for logical lookup- This seems extremly strange as you initially already have pretty much the same logic in reverse to determine the angle based in the different inputs. Unity reads back the euler angles from the quaternion representation, so it might even return a negative angles. Instead why don’t you use your “angle_to_rotate”?

Finally if you have a direction vector and you want to make sure it’s length is “1” you usually just normalize it.

However if you just want to move “forward”, why not just using “transform.forward”? It’s a world space direction vector of length 1 which represents the “blue” axis of the object in Unity (positive z).

All in all it seems way to complicated what you’re doing there.

edit
I forgot to mention that read-modify-write operations on eulerAngles are not recommended. The Quaternion to eulerAngles conversion is not unique. So at certain rotations your angles may suddenly flip. However since you always pass a fix / given y angle the result might not be what you want.

Ok i have now changed everything to one line of code

transform.Translate(Vector3.forward * 3.741f * Time.deltaTime, Space.Self);

I did not use vector3. Forward previously because the character was always moving in the worldspace, however, I did not notice that I can change the space to Space.self in the translate function, which causes him to move automatically with the rotation. Therefore all the complicated calculations.

Sry :slight_smile: