Home > Software design >  Finding angle from two Vector2 points
Finding angle from two Vector2 points

Time:01-10

I'm trying to get an angle from two Vector2 positions.

The points are found by the following raycast code:

RaycastHit2D hit = Physics2D.Raycast(groundedPos.transform.position, Vector3.down, 1, lmask); // lmask is only the blocks
Vector2 firstPos = hit.point;

RaycastHit2D hit2 = Physics2D.Raycast(groundedPos.transform.position   new Vector3(5f, 0, 0), Vector3.down, 1, lmask);
Vector2 secondPos = hit2.point;

How would I get an angle from these two Vector3 points?

I would then need to change the rotation of my object after this.

Edit:

Flat ground:

Flat

Not flat:

not flat

As you can see in the images, the red raycasts are where the raycast codes hit and they are displayed, the black square with the circle colliders is the player, and the two blocks is the thing I'm trying to change the rotation of. It is fine on flat, as you can see. But non flat it is messed up.

CodePudding user response:

Once you've got the two positions, find out the angle from the starting point to the second point, then apply the Euler rotation, rotating around the z-axis ..

transform.rotation = Quaternion.Euler ( 0, 0, Vector2.SignedAngle ( Vector2.right, secondaPos - firstPos ) );

Note - if you are trying to rotate a child of a GameObject, you might be "double" rotating the object, which is what it looks like in the images you updated your post with. If the colliders are attached to a child object, do you need to rotate that object as well?

CodePudding user response:

First a general issue with your code is the maxDistance. You are passing in 1 as the maximum distance for both your raycasts but your image shows that this might not hit the ground if it isn't flat

=> one of the positions might be "invalid" since the raycast doesn't hit the ground and therefore the value would just be a default (0, 0) which will mess up the rotation.

you either want to wrap this properly and do e.g.

var hit = Physics2D.Raycast(groundedPos.transform.position, Vector3.down, 1, lmask);
var hit2 = Physics2D.Raycast(groundedPos.transform.position   new Vector3(5f, 0, 0), Vector3.down, 1, lmask);

if(hit.collider && hit2.collider)
{
    var secondPos = hit2.point;
    var firstPos = hit.point;

    ...
}

or rather use float.PositiveInfinity as maximum distance for the rays so they will always hit something.


Then alternativ to this you can also use

var direction = secondPos - firstPos;
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg);

which might be slightly more efficient.

Or simply set

transform.right = secondaPos - firstPos;

Or in case this is about a Rigidbody2D you would rather go through

rigidbody2D.MoveRotation(Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg);
  • Related