Having trouble using Vector2.SignedAngle
Hey guys,
I'm working on a top down 2D space sim, and I need a way to calculate the ship's heading. I would normally just use heading = transform.eulerAngles.z;, but in a 2D scene, the Z axis points downwards, so instead of the degrees increasing when the ship turns right, they do the opposite, starting at 359 and decreasing.
So I'm trying a different approach: Vector2.SignedAngle.
The problem is that I can't get it to work. In a test I'm doing, I have two game objects, one representing the ship and the other representing the direction it is going in, parented to the ship object, so when the ship turns, the reference object moves accordingly to be in the direction the ship is facing.
I have the following code, but I must be doing something wrong, because it returns nothing but zero.
public Transform player;
public Transform target;
void Update()
{
Vector2 shipDir = target.position - player.position;
Vector2 forward = transform.forward;
float angle = Vector2.SignedAngle(shipDir, forward);
Debug.Log("heading = " + angle);
}
The ship object is player, and the reference object is target. If anyone can tell me what I've done incorrectly or suggest a better solution to my problem, i would really appreciate it.
What is this script attached to? And where is it's blue axis facing towards? because that is the direction transform.forward is pointing. You said your z axis are pointing down, thus transform.forward is likely not what you want here if the transform of this script is shooting straight down. If it is shooting straight down, it will be (0,0) because the z axis is not used (if it was a Vector3, you would get (0,0,1). You could always work off the world x or y axis in your case. so Vector2.SignedAngle(shipDir, Vector2.up) will give you the ship to the target direction vs the way the world y (yellow) axis is pointing. If the function returns zero, you know that it is aligned with that axis, if not, you will have te signed angle in relation to that axis at which your ship is pointing.
All that being said, you say you need to get a way to calculate which direction the ship is going, but one of the ships axis should give you that. player.up
is the direction the player object is facing on the y axis, player.right
is the x axis and player.forward
is the z axis. If you need a target direction so you know what direction you need to rotate towards for example, you get the direction with target.position - player.position
and then you rotate towards that position, like you have done with shipDir. I just mention that because it seems that you may be over complicating a simple task because in your question you state that you want to find the direction when you have already done that with shipDir.
I think you may be misunderstanding my question somewhat. I'm talking about the Z axis in world space, not the Z axis of the object itself. And in 2D mode, the up axis is Z, and the forward axis is Y. And I'm not trying to "find" the direction, but rather I'm trying to get the reading in degrees to be the same as you would see on a compass, with east being 90 and west being 270, ins$$anonymous$$d of what I have right now, which is east is 270 and west is 90.
Answer by MerlinsMaster · May 27, 2019 at 04:18 PM
I figured it out. For anyone who is having the same issue, here is the solution that worked for me:
heading = Mathf.Repeat(-transform.eulerAngles.z, 360f);
Credit goes to EmmaEwert in the Unity Forums for giving me this excellent solution.
This is not an answer to your original problem, my solution works just fine. Your question was about using SignedAngle to get the result you needed
Answer by highpockets · May 27, 2019 at 10:20 AM
I get it, like "never eat shredded wheat" instead of "never wheat shredded eat".... Anyhow, 2D mode is however you want to define it in 2D space. The world z axis can be pointing away from camera or up in your case. So you use the z instead of the y axis, but you can't get it in the way you are doing it. transform.forward is still going to return (0,0,1) if the z axis of the transform is aligned with the world z direction. Since you are using a Vector2 to save the variable, the reading will still be (0,0) because it will only save the first 2 floats of the Vector3 direction. You need to only work off the x and z plane, but you are only working off the x and y plane at the moment.
Vector3 dir = player.position - target.position;
Vector2 shipDir = new Vector2(dir.x, dir.z);
Vector2 forward = new Vector2(transform.forward.x, transform.forward.z);
float angle = Vector2.SignedAngle(shipDir, forward);
if(angle == 0.0)
{
//heading north
}
else if( angle > 0.0 && angle < 90 )
{
//heading north east
}
else if( angle == 90 )
{
//heading east
}
//etc. etc. etc.
Debug.Log("heading = " + angle);
Hopefully that helps