- Home /
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 :)
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.
You're not rotating towards a final angle but by the angle all the time.
If I were you, I'd create the final look direction and Slerp towards it. Rotating a global Vector3.forward by your degree ships give you that.
But the Problem is not that the character is not rotating correctly but that the character moves unpredictable
Answer by Bunny83 · Aug 30, 2017 at 09:21 AM
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.
Answer by Kaskorian · Aug 30, 2017 at 09:52 AM
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 :)
Your answer
Follow this Question
Related Questions
Enemy strafing AI Top Down 0 Answers
How to make an object go the direction it is facing? 6 Answers
Unity2D, How do i check which way a sprite is facing? 1 Answer
Making a bubble level (not a game but work tool) 1 Answer
How to calculate xSpeed and ySpeed according to float value of rotation? 1 Answer