问题
In Unreal, I want
- to rotate an actor where the forward vector points at target's current position,
- to ensure that the up vector of my actor is the same at the up vector of my target
In Unity3D, it's super simple. It's a single line of code (source):
transform.LookAt(target, Vector3.up);
In blueprint, there's a Node called "Find Look at Rotation". The problem is that there's no Up vector parameter, so when you are close to the target, you can have a unwanted roll rotation.
So, how can I create the equivalent of Unity LookAt in Unreal blueprint?
回答1:
I modified a solution I found here:
https://forums.unrealengine.com/development-discussion/c-gameplay-programming/1482788-posting-the-source-code-for-lookrotation-for-those-who-need-it
The source actor was looking the target with his z vector (Up vector in Unreal). I changed it to be the x vector because in Unreal, the forward vector is the x axis.
The lookAt parameter is the position of the actor you want to look at (the target). UpDirection is the up vector of the target you want to match with the up vector of the source.
Just set the rotation of the source with the FRotator value returned by the function below, called in the C++ code of the source:
FRotator MyLookRotation(FVector lookAt, FVector upDirection)
{
FVector forward = lookAt - GetActorLocation();
FVector up = upDirection;
forward = forward.GetSafeNormal();
up = up - (forward * FVector::DotProduct(up, forward));
up = up.GetSafeNormal();
///////////////////////
FVector vector = forward.GetSafeNormal();
FVector vector2 = FVector::CrossProduct(up, vector);
FVector vector3 = FVector::CrossProduct(vector, vector2);
float m00 = vector.X;
float m01 = vector.Y;
float m02 = vector.Z;
float m10 = vector2.X;
float m11 = vector2.Y;
float m12 = vector2.Z;
float m20 = vector3.X;
float m21 = vector3.Y;
float m22 = vector3.Z;
float num8 = (m00 + m11) + m22;
FQuat quaternion = FQuat();
if (num8 > 0.0f)
{
float num = (float)FMath::Sqrt(num8 + 1.0f);
quaternion.W = num * 0.5f;
num = 0.5f / num;
quaternion.X = (m12 - m21) * num;
quaternion.Y = (m20 - m02) * num;
quaternion.Z = (m01 - m10) * num;
return FRotator(quaternion);
}
if ((m00 >= m11) && (m00 >= m22))
{
float num7 = (float)FMath::Sqrt(((1.0f + m00) - m11) - m22);
float num4 = 0.5f / num7;
quaternion.X = 0.5f * num7;
quaternion.Y = (m01 + m10) * num4;
quaternion.Z = (m02 + m20) * num4;
quaternion.W = (m12 - m21) * num4;
return FRotator(quaternion);
}
if (m11 > m22)
{
float num6 = (float)FMath::Sqrt(((1.0f + m11) - m00) - m22);
float num3 = 0.5f / num6;
quaternion.X = (m10 + m01) * num3;
quaternion.Y = 0.5f * num6;
quaternion.Z = (m21 + m12) * num3;
quaternion.W = (m20 - m02) * num3;
return FRotator(quaternion);
}
float num5 = (float)FMath::Sqrt(((1.0f + m22) - m00) - m11);
float num2 = 0.5f / num5;
quaternion.X = (m20 + m02) * num2;
quaternion.Y = (m21 + m12) * num2;
quaternion.Z = 0.5f * num5;
quaternion.W = (m01 - m10) * num2;
return FRotator(quaternion);
}
回答2:
You can use Make Rot From XZ
to do this pretty easily:
And for the default unity value of worldUp
, you would use (0,0,1)
for that.
Calling it on tick with a cube (with forward&up directions shown) as LookingActor
, the position of the player character (mannequin) position as TargetPosition
, and (0,0,1)
as WorldUp
produces a result like this:
And if you'd rather tuck away the function definition in C++:
void UMyBlueprintFunctionLibrary::MyLookAt(AActor LookingActor, FVector TargetPosition,
FVector WorldUp = FVector::UpVector)
{
FVector Forward = TargetPosition - LookingActor.GetActorLocation();
FRotator Rot = UKismetMathLibrary::MakeRotFromXZ(Forward, WorldUp);
LookingActor.SetActorRotation(Rot, true);
}
回答3:
I'm not familiar with unreal but look at is basically this:
yourLocation-target location this is a vector to the target then you should do this thing
cosInvert((a*b)/|a|*|b|)
this will give you the angle you should look at
- a will be to the target angle
- and b will be (0,0,1),(0,1,0),(1,0,0)
Now you have 3 angles to set to the rotation of your object.
来源:https://stackoverflow.com/questions/58719951/how-can-i-create-the-equivalent-of-unity-lookat-in-unreal-blueprint