SpringArmComponent
工作原理
SpringArmComponent是常用的相机辅助组件,主要作用是快速实现第三人称视角(包括相机避障等功能)
核心函数是UpdateDesiredArmLocation,注册时和每帧都会调用该函数来计算相机位置
void USpringArmComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
UpdateDesiredArmLocation(bDoCollisionTest, bEnableCameraLag, bEnableCameraRotationLag, DeltaTime);
}
具体位置更新是通过将计算后将结果写入RelativeSocketLocation和RelativeSocketRotation,通过重载GetSocketTransform和调用UpdateChildTransform(Child就是Camera)来实现相机位置更新
void USpringArmComponent::UpdateDesiredArmLocation(bool bDoTrace, bool bDoLocationLag, bool bDoRotationLag, float DeltaTime)
{
......
// Form a transform for new world transform for camera
FTransform WorldCamTM(DesiredRot, ResultLoc);
// Convert to relative to component
FTransform RelCamTM = WorldCamTM.GetRelativeTransform(GetComponentTransform());
// Update socket location/rotation
RelativeSocketLocation = RelCamTM.GetLocation();
RelativeSocketRotation = RelCamTM.GetRotation();
UpdateChildTransforms();
}
FTransform USpringArmComponent::GetSocketTransform(FName InSocketName, ERelativeTransformSpace TransformSpace) const
{
FTransform RelativeTransform(RelativeSocketRotation, RelativeSocketLocation);
......
return RelativeTransform;
}
计算旋转
相关参数
相关代码
FRotator USpringArmComponent::GetTargetRotation() const
{
FRotator DesiredRot = GetDesiredRotation();
if (bUsePawnControlRotation)
{
if (APawn* OwningPawn = Cast<APawn>(GetOwner()))
{
const FRotator PawnViewRotation = OwningPawn->GetViewRotation();
if (DesiredRot != PawnViewRotation)
{
DesiredRot = PawnViewRotation;
}
}
}
// If inheriting rotation, check options for which components to inherit
if (!IsUsingAbsoluteRotation())
{
const FRotator LocalRelativeRotation = GetRelativeRotation();
if (!bInheritPitch)
{
DesiredRot.Pitch = LocalRelativeRotation.Pitch;
}
if (!bInheritYaw)
{
DesiredRot.Yaw = LocalRelativeRotation.Yaw;
}
if (!bInheritRoll)
{
DesiredRot.Roll = LocalRelativeRotation.Roll;
}
}
return DesiredRot;
}
UsingAbsoluteRotation是SceneComponent的一个设置,一般来说都是false(即使用相对值),可以在这里设置
工作原理
GetDesiredRotation返回的就是当前的Rotation(相对于世界),这个函数最终的返回值也是作为绝对旋转的值(相对于世界)
所以如果不继承某个轴的旋转并且使用相对旋转或者使用绝对旋转的话就会导致在该轴上相机不会随着父物体旋转(总是保持初始设置的相对旋转作为绝对旋转);反之在某个轴上继承了旋转并且使用相对旋转,这时如果选择了UsePawnControlRotation的话就会使用Controller中的旋转,否则跟着父物体旋转(即返回DesiredRotation)
继承旋转的含义就是随着父物体旋转
常用案例
- 第三人称自由相机视角,将鼠标xy轴输入存入Controller中(Yaw和Pitch),使用相对旋转,UsePawnControlRotation设置为true。人物的移动方向获取Controller(也就是相机)的前和右(先去除Controller的pitch和roll分量再计算)