How can I create the equivalent of Unity LookAt in Unreal blueprint?

孤街醉人 提交于 2020-06-08 19:51:44

问题


In Unreal, I want

  1. to rotate an actor where the forward vector points at target's current position,
  2. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!