Angle between two vectors not calculating properly

I’m trying to find the angle (between -180 and 180) between an actor’s forward vector and the vector necessary to point towards another target actor. I was able to get something somewhat working using other answers, but I’m getting weird output in some situations and I’m not sure why. When the primary actor is rotated to be directly at or away from the target, the correct angles are showing (left side of the screen). The problem seems to be that the angle is not capped at 180 - at a certain rotation I can get it to output a 193 angle. Any ideas why I’m not getting a clean angle out of this blueprint in all cases? The game is 2D (all actors are centered at 0z, x and y are the only locations that change) if that matters.




This won’t work because you’re not taking Z into account :slight_smile:

You can only cut Z out of the equations if everything is located at the same Z, and that never varies.

Sorry I didn’t clarify - I had a hard time getting this to post and had to retype it a few times. All actors are at the same Z coordinate; the only thing that changes is X and Y.

Since you’re doing it in pseudo 2d (no Z), perhaps you could simplify it to this:

You could also try:
ACOSD( Normalized (Other Actor Location - Self Location) · Self Forward vector) ← it should give you the difference in degrees but not on what side.

· ← dot product

To know what side do the same but with the right vector. Negative = left meaning rotate counter clock, Positive = right meaning rotate clockwise.

Thank you so much - this works correctly and I’m not seeing any number above 180. I tried using the right vector and it is basically just turning the angle 90deg, but I’m still not seeing pos/neg. Is there another way I could figure that out?

The result with the right vector is to only multiply -1 the result of the forward vector to give it direction.

Basically: If result with right vector > 0 → result of forward vector * -1, else result with forward vector.

I’m never getting a result with the right vector that is less < 0. I’ve included a shot of the blueprint below in case I’ve smoothbrained it somehow.

EDIT: my bad… for the right vector dont do ACOSD… That is why you are not getting any negative numbers.

Slight correction here too, just flipped the >.

:point_up_2: This is the result.

1 Like

The dot product alone is enough to tell you the direction (positive/negative).
You just need to dot the forward vector of the moving thing vs the location of the other item.

When facing away from it you will get a negative result. When looking towards it it will be a positive result.
(In most cases anyway? There’s edge situations where you may want to dot the cross of an actor Up vector/right vector or similar).

Dot should always range between -1 and 1.
Obviously dot is also a ratio of the angle needed to reach the rotation required to look at the object.

Unit circles and all that?
(If that doesn’t ring a bell, have a quick search online for a unit circle explanation)

Instead of using acosd you can just solve the angle value in degrees from the dot itself…
Making sure you preserve the sign…

1 Like

Just to illustrate further:

  • ACOSD ( 1 ) = 0
  • ACOSD ( 0.5 ) = 60
  • ACOSD( 0 ) = 90
  • ACOSD ( -0.5 ) = 120
  • ACOSD( -1 ) = 180

Not to revive this from the dead… just wanted to share this:

1 Like

There’s no like function to QA stuff unfortunately.
You should share the code for that (in cpp) just to create a plot twist :stuck_out_tongue:

Ah, ■■■■. :rofl: in a few hours.

This solved the problem perfectly - thank you!!

1 Like

chipmunk-dramatic

image

UFUNCTION(BlueprintPure, Category="CustomFunctions")
		static void F_YawToTarget(
			const USceneComponent* start,
			const USceneComponent* target,
			float& YawDEG);
#include "CustomFunctions.h"
#include "Math/UnrealMathUtility.h"

void UCustomFunctions::F_YawToTarget(
	const USceneComponent* start,
	const USceneComponent* target,
	float& YawDEG)
{
	FVector dir = (target->GetComponentLocation() - start->GetComponentLocation()).GetSafeNormal();

	float ForwardDotProduct = start->GetForwardVector() | dir;
	float RightDotProduct = start->GetRightVector() | dir;

	if (RightDotProduct > 0.f)
		YawDEG = FMath::Acos(ForwardDotProduct) * (180.f) / PI * (-1.f);
	else
		YawDEG = FMath::Acos(ForwardDotProduct) * (180.f) / PI;
}
1 Like