装弹动画
2023年9月7日 2024年1月11日
说明
- 已在弹夹子弹耗尽时实现自动装弹逻辑
- 现在实现手动装弹的第一步, 播放装弹动画
- 步枪和发射器各有一个装弹动画, 使用动画剪辑实现
概览
- 创建两个动画剪辑资产, 并设置SlotName
- 绑定手动装弹键位
- 将武器信息封装到数据结构
- 更换武器时, 更新对应的装弹动画
创建动画剪辑资产
-
为装弹动画绑定骨骼HeroTPP_Skeleton, 创建对应的动画剪辑资产, 保存到Player/Animations
- Launcher_Reload AM_Launcher_Reload Reload AM_Reload -
设置动画剪辑的SlotName, 选择UpperBody
绑定装弹键位
项目设置 > Engine > Input
- | |
---|---|
类型 | Action Mappings |
函数描述 | Reload |
键位 | R |
搭建手动装弹框架
添加空的Reload函数
ShootThemUp: Components/STUWeaponComponent.h
public
1void Reload();
ShootThemUp: Components/STUWeaponComponent.cpp
1void USTUWeaponComponent::Reload() 2{ 3 PlayAnimMontage(CurrentReloadAnimMontage); 4}
绑定函数描述和回调函数
ShootThemUp: Player/STUBaseCharacter.cpp
1// SetupPlayerInputComponent 2PlayerInputComponent->BindAction("Reload", IE_Pressed, WeaponComponent, &USTUWeaponComponent::Reload);
将武器信息封装到数据结构
当前, 不同武器有各自的武器类属性, 结合装弹动画, 定义存放武器信息的数据结构
定义数据结构存放武器信息
ShootThemUp: Components/STUWeaponComponent.h
1USTRUCT(BlueprintType) 2struct FWeaponData 3{ 4 GENERATED_USTRUCT_BODY() 5 UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon") 6 TSubclassOf<ASTUBaseWeapon> WeaponClass; 7 8 UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Weapon") 9 UAnimMontage *ReloadAnimMontage; 10};
在武器组件类添加数组成员, 存放武器信息
protected
ShootThemUp: Components/STUWeaponComponent.h
1UPROPERTY(EditDefaultsOnly, Category = "Weapon") 2TArray<FWeaponData> WeaponData;
屏蔽武器类属性
ShootThemUp: Components/STUWeaponComponent.h
创建武器时, 依据数组信息
注意: 若创建武器失败, 继续创建其他武器
ShootThemUp: Components/STUWeaponComponent.cpp
1// SpawnWeapons 2 for (auto OneWeaponData : WeaponData) 3 { 4 auto Weapon = GetWorld()->SpawnActor<ASTUBaseWeapon>(OneWeaponData.WeaponClass); 5 if (!Weapon) continue; 6 Weapons.Add(Weapon); 7 Weapon->SetOwner(Character); 8 AttachWeaponToSocket(Weapon, Character->GetMesh(), WeaponArmorySocketName); 9 }
添加属性, 指向当前装弹动画
private
经常需要播放装弹动画
ShootThemUp: Components/STUWeaponComponent.h
1UPROPERTY() 2UAnimMontage *CurrentReloadAnimMontage = nullptr;
更换武器时, 更新装弹动画
EquipWeapon
ShootThemUp: Components/STUWeaponComponent.cpp
进入时检查WeaponIndex
1if (WeaponIndex < 0 || WeaponIndex >= Weapons.Num()) 2{ 3 UE_LOG(LogWeaponComponent, Warning, TEXT("Invalid weapon index")); 4 return; 5}
不使用武器标号获取动画剪辑
- 创建武器时, 根据WeaponData元素顺序
- 存在武器创建失败的情况, 后续可能需要对武器进行排序
1// CurrentReloadAnimMontage = WeaponData[WeaponIndex].ReloadAnimMontage;
根据武器类型, 查找对应的武器信息
使用lambda表达式实现查找谓语
- 对调用运算符进行重载
- 使用lambda表达式实现一元谓语, 捕获引用, 比对武器类型, 返回true或false
- 若匹配元素个数为0或大于1, 查找函数返回nullptr
1const auto CurrentWeaponData = WeaponData.FindByPredicate([&](const FWeaponData &Data){ // 2 return Data.WeaponClass == CurrentWeapon->GetClass(); // 3});
设置当前武器的装弹动画剪辑
1CurrentReloadAnimMontage = CurrentWeaponData ? CurrentWeaponData->ReloadAnimMontage : nullptr;
设置游戏角色的WeaponData数组
打开BP_STUBaseCharacter, 选中WeaponComponent, 去到Details > Weapon > WeaponData