Mathematical Tips
September 15, 2024About 3 min
Mathematical Tips
自定义两Actor旋转数值
FRotator Rotation = (ActorA->GetActorLocation() - ActorB->GetActorLocation()).Rotation();
Rotation.Pitch = 45.f;
const FVector ToTarget = Rotation.Vector();
以上代码的意义是,从B
到A
的向量在Pitch方向旋转45度得到ToTarget
方向向量,且该值是进行了标准化操作。这个也太方便了吧。
这里Rotation
方法其实就是ToOrientationRotator
。
Direction vs ForwardVector
FVector Direction = ActorA->GetActorRotation().Vector();
FVector ForwardVector = GetActorForwardVector();
以上的Direction
与ForwardVector
这两个值是相同的。
提取动画根节点位移后转为角色的世界坐标
const FTransform ActorToWorld = GetOwner()->GetTransform();
const FTransform ComponentToActor = ActorToWorld.GetRelativeTransform(GetComponentTransform());
const FTransform NewComponentToWorld = InTransform * GetComponentTransform();
const FTransform NewActorTransform = ComponentToActor * NewComponentToWorld;
来源:USkeletalMeshComponent::ConvertLocalRootMotionToWorld
FRotationMatrix::MakeFromX(DesiredXAxis).Rotator()
将 Actor 的正方向(即其本地 X 轴)旋转到与 DesiredXAxis
世界空间方向对齐,同时自动计算合理的 Y 和 Z 轴方向以保持正交性。
具体行为解析:
MakeFromX(DesiredXAxis)
- 以输入的
DesiredXAxis
(世界空间方向向量)作为 新的 X 轴。 - 自动计算 Y 和 Z 轴:引擎会通过叉积运算生成与 X 轴正交的 Y 和 Z 轴(具体逻辑可能依赖虚幻引擎的右手坐标系规则)。
- 以输入的
.Rotator()
- 将生成的旋转矩阵转换为
FRotator
(Pitch/Yaw/Roll),可直接用于设置 Actor 的旋转。
- 将生成的旋转矩阵转换为
最终效果
- Actor 的 本地 X 轴(通常是其正前方向)会完全对齐到
DesiredXAxis
方向。 - Actor 的 Y 和 Z 轴会根据引擎的默认正交化规则调整(可能不是唯一的解,但保证合理性)。
- Actor 的 本地 X 轴(通常是其正前方向)会完全对齐到
示例场景
假设有一个角色需要面朝移动方向(X 轴对齐速度方向):
// 获取角色当前的移动速度方向(世界空间)
FVector MovementDirection = GetVelocity().GetSafeNormal();
// 生成使X轴对齐移动方向的旋转
FRotator TargetRotation = FRotationMatrix::MakeFromX(MovementDirection).Rotator();
// 应用到角色
Character->SetActorRotation(TargetRotation);
此时,角色的 正前方(X轴) 将严格指向移动方向。
注意事项
其他轴向的不确定性
- 仅约束 X 轴时,Y/Z 轴的方向由引擎自动计算(可能依赖内部叉积顺序)。如果需要精确控制其他轴,需使用
MakeFromXY()
或MakeFromXZ()
。
- 仅约束 X 轴时,Y/Z 轴的方向由引擎自动计算(可能依赖内部叉积顺序)。如果需要精确控制其他轴,需使用
万向节锁问题
- 当
DesiredXAxis
接近垂直(如FVector(0,0,1)
)时,转换到FRotator
可能出现歧义(Pitch ±90° 时的万向节锁)。
- 当
归一化要求
- 输入向量必须是非零向量(通常先用
GetSafeNormal()
处理)。
- 输入向量必须是非零向量(通常先用
对比其他方法
如果希望 Actor 的某个特定轴(非X轴)对齐目标方向,需改用其他方法:
// 让Actor的Z轴指向目标方向 FRotator TargetRotation = FRotationMatrix::MakeFromZ(DesiredZAxis).Rotator();
如果需要 完全控制所有轴向,使用
MakeFromXY()
或MakeFromXZ()
:// 明确指定X和Y轴方向(Z轴自动正交化) FRotationMatrix::MakeFromXY(DesiredXAxis, DesiredYAxis).Rotator();
总之,MakeFromX().Rotator()
是 最直接的方式 让 Actor 的 X 轴对齐目标方向,适用于大多数"面朝方向"的需求。
关于插值使用
通常来说使用线性插值时,我们会定死一个起始点和结束点,来叠加Alpha
值,如下:
float Alpha += DeltaTime * Speed;
float Value = Lerp(A,B,Alpha);
这里的Alpha
是需要缓存起来,实时计算。
有另一种做法,固定Alpha
值,也就是速率,缩短行程。这种做法适用于更改一个值,这个值一直作为起点。比如想平滑移动一个物体到特殊的位置,这个物体的位置就作为A
来计算,如下:
float Alpha = DeltaTime * Speed;
A = Lerp(A,B,Alpha);