简体   繁体   中英

Finding angle from two Vector2 points

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:

平坦的

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.

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?

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 eg

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

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

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

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

var firstPos = hit.point;
var secondPos = hit2.point;
...

Then alternativ to this you can also use

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

which might be slightly more efficient.

Or simply set

transform.right = direction;

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM