同步系列14-瞄准偏移的设置和应用


要让角色持有武器的时候上半身枪随鼠标的偏移走,需要创建瞄准偏移动画。因为我这里的角色分为手持和瞄准两种动画状态,所以需要创建两个瞄准偏移,先创建手持的。

image-20230505113458975

选择我们角色所使用的骨骼后就能创建成功。

image-20230505113653457

复制九份Aim_Space_Hip的动画,进去后调整到想要的动画帧数,右键红色的指针,移除指定帧之前的帧以及之后的帧,只保留当前姿势的帧。保存后就可以按如下格式命名:

image-20230505113941790

其中AO_Zero是AO_CC姿势的复制,用作设置为附加动画的基础姿势。其他所有的动画在附加设置那里设置动画类型为网格体空间,基础姿势类型为选择的动画帧,基础姿势动画选择为刚刚复制的AO_zero。这样九个方向的持枪动画就能用了。同理,瞄准动画的瞄准偏移也按照这种方法做,以最后做出来九个方向的瞄准动画和一个基础姿势动画,别忘了个九个瞄准动画添加基础姿势。

image-20230505114400339

在之前创建的两张瞄准偏移中添加对应的动画:

image-20230505115102033

image-20230505115034873

在前面的设置中横向和纵向我们设置了Yaw和Pitch,为了在动画蓝图中使用这两个值,需要在C++中获取。在角色的C++类中,添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
protected:
void AimOffset(float DeltaTime);
float AO_Yaw;
float AO_Pitch;
FRotator StartingAimRotation;
public:
FORCEINLINE float GetAO_Yaw() const { return AO_Yaw;}
FORCEINLINE float GetAO_Pitch() const { return AO_Pitch;}

void ABlasterCharacter::AimOffset(float DeltaTime)
{
if(CombatComp && CombatComp->EquippedWeapon == nullptr) return;//如果没这个组件或者手上没武器 是不需要执行这个函数的
AO_Pitch = GetBaseAimRotation().Pitch;//控制持枪动画的上下,不管是第一人称还是第三人称都需要
if(AO_Pitch > 90.f && !IsLocallyControlled())//在网络传输过程中,Pitch会从float压缩成unsigned进行传输从而丢失正负,需要进行转换
{
//将AO_Pitch从[270,360)映射到[-90,0];
FVector2D InRange(270.f,360.f);
FVector2d OutRange(-90.f,0.f);
AO_Pitch = FMath::GetMappedRangeValueClamped(InRange,OutRange,AO_Pitch);
}
if(IsFirstPerson())//第一人称枪在手,Yaw随鼠标走
{
bUseControllerRotationYaw = true;
StartingAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f);
AO_Yaw = 0;
return;
//无需处理后面的
}
//处理第三人称下的偏移
FVector Velocity = GetVelocity();
Velocity.Z = 0.f;
//设置速度
float Speed = Velocity.Size();
//是否在空中
bool bIsInAir = GetCharacterMovement()->IsFalling();

if(Speed == 0.f && !bIsInAir)//静止状态没有跳跃
{
FRotator CurrentAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f);
FRotator DeltaAimRotation = UKismetMathLibrary::NormalizedDeltaRotator(CurrentAimRotation,StartingAimRotation);
AO_Yaw = DeltaAimRotation.Yaw;
bUseControllerRotationYaw = false;
}
if(Speed >0.f || bIsInAir)//奔跑或者跳跃
{
StartingAimRotation = FRotator(0.f, GetBaseAimRotation().Yaw, 0.f);
bUseControllerRotationYaw = true;
}
}

//AimOffset函数在Tick函数中调用

之后在动画实例的C++类中添加:

1
2
3
4
5
6
7
8
9
10
11
12
private:
UPROPERTY(BlueprintReadOnly, Category = Anim, meta = (AllowPrivateAccess = "true"))
float AO_Yaw;

UPROPERTY(BlueprintReadOnly, Category = Anim, meta = (AllowPrivateAccess = "true"))
float AO_Pitch;

void UBlasterAnimInstance::NativeUpdateAnimation(float DeltaTime)
{
AO_Yaw = BlasterCharacter->GetAO_Yaw();
AO_Pitch = BlasterCharacter->GetAO_Pitch();
}

随后在动画蓝图中创建AimOffset状态机

image-20230505114848045

image-20230505115720118

这样就做完了。可以看到玩家持有枪械的时候动画和瞄准的方向是一致的。关于瞄准时其它客户端Pitch的bug下一节说明。

image-20230505115900332


文章作者: John Doe
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 John Doe !
  目录