【问题标题】:How can I create the equivalent of Unity LookAt in Unreal blueprint?如何在 Unreal 蓝图中创建等效的 Unity LookAt?
【发布时间】:2020-03-02 08:02:38
【问题描述】:

在虚幻中,我想要

  1. 旋转前向矢量指向目标当前位置的actor,
  2. 确保我的actor的上向量与我的目标的上向量相同

在 Unity3D 中,这非常简单。这是一行代码(source):

transform.LookAt(target, Vector3.up);

在蓝图中,有一个名为“Find Look at Rotation”的节点。问题是没有向上矢量参数,所以当您靠近目标时,可能会出现不必要的滚动旋转。

那么,如何在 Unreal 蓝图中创建相当于 Unity LookAt 的功能?

【问题讨论】:

    标签: c++ vector rotation unreal-engine4 unreal-blueprint


    【解决方案1】:

    您可以使用Make Rot From XZ 轻松完成此操作:

    对于 worldUp 的默认统一值,您可以使用 (0,0,1)

    使用立方体(显示向前和向上方向)在刻度上调用它为LookingActor,玩家角色(人体模型)的位置为TargetPosition(0,0,1)WorldUp,产生如下结果:


    如果您宁愿隐藏 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);
    }
    

    【讨论】:

    • 这个解决方案的问题和 find look at rotation 节点是一样的。它会导致不必要的旋转,因为您没有将目标的上向量放置在与源上向量位置相同的位置。演员没有被锁定,它会导致滚动旋转。
    • @ÉmilePettersen-Coulombe 向上向量没有位置,它们只有方向......而且它对我来说很好。
    • @ÉmilePettersen-Coulombe Please see here 以 WorldUp=(0,0,1) 为例。我建议您参考MakeRotFromXZ 上的文档,因为它做了FindLookAtRotation 没有做的事情。
    • @ÉmilePettersen-Coulombe 我还是不太清楚你在说什么,你能详细说明一下吗?
    【解决方案2】:
    inline FQuat MyLookAt(const FVector& lookAt, const FVector& upDirection)
    {
        return FRotationMatrix::MakeFromXZ(lookAt, upDirection).ToQuat();
    }
    

    【讨论】:

      【解决方案3】:

      我修改了在这里找到的解决方案:

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

      源actor正在使用他的z向量(虚幻中的向上向量)查看目标。我把它改成了 x 向量,因为在 Unreal 中,前向向量是 x 轴。

      lookAt 参数是您要查看的演员(目标)的位置。 UpDirection 是你要匹配的目标的上向量与源的上向量。

      只需用下面函数返回的FRotator值设置源的旋转,在源的C++代码中调用:

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

      【讨论】:

      • 这正是我要找的!谢谢!
      • 为什么不在FVector forward = lookAt - GetActorLocation();之后简单地return UKismetMathLibrary::MakeRotFromXZ(forward.GetSafeNormal(), upDirection.GetSafeNormal());
      • 是的,所有这些代码到底是怎么回事?
      【解决方案4】:

      我不熟悉虚幻 但 看看基本上是这样的:

      yourLocation-目标位置 这是一个指向目标的向量 那你应该做这件事

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

      这将为您提供您应该查看的角度

      • a 将是目标角度
      • b 将是 (0,0,1),(0,1,0),(1,0,0)

      现在您可以设置 3 个角度来设置对象的旋转。

      【讨论】:

      • 如何用您的解决方案定义向上向量?我希望它与目标相同。
      猜你喜欢
      • 1970-01-01
      • 2020-06-07
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      相关资源
      最近更新 更多