Reputation: 11
I'm working on a 2D game in XY plane. I've created enemies using NavMeshAgent and I've gave my agents way pints to move between them. The problem is that I don't know how to rotate them in the direction they are moving or vector of the velocity (blue arrow). The front of the agent is in the direction of Y axis(green arrow). Note that updateRotation isn't an option, That will rotate agent and make it disappear(agent rotates 90 degree around X axis).
here's the a code that i have found on unity forum, it works perfectly on 3D, but i can't make it work on 2D
void FaceTarget()
{
Vector3 direction = agent.steeringTarget;
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5);
}
I've tried this code, It calculates the angel between the vector of the velocity and local Y axis. Desired output is that agent rotates toward its movement direction. In the actual output, agent rotates, But in some points, It's not toward the movement direction. I know the problem is that angels range is [0,180], not [0,360], But I can't figure out any solution for it.
void FaceTarget()
{
Vector3 lookTarget = agent.velocity.normalized;
float angel = Vector3.Angle(lookTarget, Vector3.up);
transform.rotation = Quaternion.Euler(0,0,angel);
}
Upvotes: 0
Views: 1569
Reputation: 11
I've solved it with help of ChatGpt. Here's the code
void FaceTarget()
{
if (agent.velocity != Vector3.zero)
{
Vector3 moveDirection = new Vector3(agent.velocity.x, agent.velocity.y, 0f);
if (moveDirection != Vector3.zero)
{
float angel = Mathf.Atan2(moveDirection.x, moveDirection.y) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angel, Vector3.back);
}
}
}
Here's another code provided by @DMGregory
void FaceTarget() {
var vel = agent.velocity;
vel.z = 0;
if (vel != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(Vector3.forward, vel);
}
}
Upvotes: 0
Reputation: 347
UPDATE: Changed to work with the 2d plane which is x-y while the original was a 2d plane in 3d which is x-z.
The steeringTarget is not equivalent to the direction vector. Its the position of the target vector to get to. The desired direction is more analogous to the steeringTarget - the agent's current position.
The actual direction of movement can be derived from agent.velocity.
Your code above could be changed to:
void FaceTarget()
{
Vector3 direction = agent.velocity;
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, direction.y, 0));
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5);
}
One issue with this though is that at low speeds this will result in the visible rotation will turn wildly and seemingly at random. To make sure this does not occur, consider applying a velocity threshold to the rotation as shown below:
void FaceTarget()
{
if(agent.velocity.magnitude > MINIMUM_SPEED)
{
Vector3 direction = agent.velocity;
Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x, direction.y, 0));
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * 5);
}
}
Finally, consider rotating a visuals only subobject instead of the main transform if you run into any issues.
Upvotes: 1