web-dev-qa-db-ja.com

UnrealブループリントでUnity LookAtに相当するものを作成するにはどうすればよいですか?

アンリアルでは、

  1. フォワードベクトルがターゲットの現在の位置を指すようにアクターを回転させるには、
  2. 私の俳優のアップベクターが私のターゲットのアップベクターと同じであることを確認するため

Unity3Dでは、とてもシンプルです。 1行のコードです( source ):

transform.LookAt(target, Vector3.up);

ブループリントには、Nodeと呼ばれる「Find Look at Rotation」があります。問題は、アップベクトルパラメーターがないため、ターゲットの近くにいるときに、不要なロール回転が発生する可能性があることです。

では、Unity LookAtに相当するものをアンリアルブループリントで作成するにはどうすればよいですか?

2
probitaille

私はここで見つけた解決策を変更しました:

https://forums.unrealengine.com/development-discussion/c-gameplay-programming/1482788-posting-the-source-code-for-lookrotation-for-those-who-need-it

ソースアクターは、zベクトル(Unrealのアップベクトル)でターゲットを探していました。 Unrealでは、フォワードベクトルがx軸であるため、これをxベクトルに変更しました。

LookAtパラメータは、見たいアクター(ターゲット)の位置です。 UpDirectionは、ソースのアップベクトルと一致させるターゲットのアップベクトルです。

ソースのC++コードで呼び出される以下の関数によって返されるFRotator値でソースの回転を設定するだけです。

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);
}

enter image description here

Make Rot From XZを使用すると、これをかなり簡単に実行できます。

blueprint implementation

そして、worldUpのデフォルトの単位値では、(0,0,1)を使用します。

ティックで、立方体(順方向と上方向を表示)をLookingActor、プレーヤーキャラクター(マネキン)の位置をTargetPosition(0,0,1)WorldUpは、次のような結果を生成します。

animation showing block facing mannequin


また、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);
}
2
Ruzihm

私はアンリアルに慣れていませんが、基本的にはこれを見てください:

yourLocation-target locationこれはターゲットへのベクトルであり、これを行う必要があります

cosInvert((a*b)/|a|*|b|)

これはあなたが見るべき角度を与えます

  • aはターゲット角度になります
  • そしてbは(0,0,1)、(0,1,0)、(1,0,0)になります

これで、オブジェクトの回転に設定する3つの角度があります。

0
nobodyMore