切换武器
2023年8月26日 2024年1月11日
概览
- 为HeroTPP添加Socket, 在背后挂载未使用武器
- 绑定键位, 按下Tab或滚动鼠标时切换武器
- 游戏角色死亡后, 销毁武器
- 处理Rifle开火定时器
为骨骼网格体添加Socket
虚幻编辑器
-
打开Content/ExternalContent/Animation/Characters/HeroTPP/HeroTPP
-
选择骨骼b_Spine1, 添加Socket
-
在细节面板设置Socket
- Socket Name ArmorySocket Relative Location (-9, -26, -23) Relative Rotation (-10, 70, -29) -
为Socket添加预览资产, 选择Launcher
武器未使用时背在背上
绑定切换武器键位
项目设置 > Engine > Input > Action Mappings
- | |
---|---|
函数描述 | NextWeapon |
键位 | Tab / MouseWheelUp / MouseWheelDown |
不论滚轮方向, 切换到下一个武器
搭建框架
切换逻辑在STUWeaponComponent中
添加空的回调函数
ShootThemUp: Components/STUWeaponComponent.h
public
1void NextWeapon();
ShootThemUp: Components/STUWeaponComponent.cpp
1void USTUWeaponComponent::NextWeapon() 2{ }
绑定回调函数和函数描述
ShootThemUp: Player/STUBaseCharacter.cpp
1// SetupPlayerInputComponent 2 3PlayerInputComponent->BindAction("NextWeapon", IE_Pressed, WeaponComponent, &USTUWeaponComponent::NextWeapon);
调整当前逻辑
修改Socket名
现在附加武器的Socket有两个, 原先的Socket为装载武器Socket
ShootThemUp: Components/STUWeaponComponent.h
WeaponAttachPointName -> WeaponEquipSocketNameShootThemUp: Components/STUWeaponComponent.cpp
1// SpawnWeapon 2WeaponAttachPointName -> WeaponEquipSocketName
添加接口: 将武器挂载到指定Socket
切换武器时使用
定义
ShootThemUp: Components/STUWeaponComponent.h
private
1void AttachWeaponToSocket(ASTUBaseWeapon *Weapon, USceneComponent *SceneComponent, const FName &SocketName);
ShootThemUp: Components/STUWeaponComponent.cpp
1void USTUWeaponComponent::AttachWeaponToSocket(ASTUBaseWeapon *Weapon, USceneComponent *SceneComponent, const FName &SocketName) 2{ 3 if (!Weapon || !SceneComponent) return; 4 FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, false); 5 Weapon->AttachToComponent(SceneComponent, AttachmentRules, SocketName); 6}
调用
ShootThemUp: Components/STUWeaponComponent.cpp
1// SpawnWeapon 2AttachWeaponToSocket(CurrentWeapon, Character->GetMesh(), WeaponEquipSocketName);
武器数组
武器组件管理武器数组
将武器类属性改为武器类属性数组
protected
ShootThemUp: Components/STUWeaponComponent.h
1UPROPERTY(EditDefaultsOnly) 2TArray<TSubclassOf<ASTUBaseWeapon>> WeaponClasses;
添加武器数组
private
ShootThemUp: Components/STUWeaponComponent.h
1UPROPERTY() 2TArray<ASTUBaseWeapon*> Weapons;
添加数据成员: 保存挂载点名称
protected
ShootThemUp: Components/STUWeaponComponent.h
1UPROPERTY(EditDefaultsOnly) 2FName WeaponArmorySocketName = "ArmorySocket";
动态生成武器时, 生成Rifle和Launcher, 先全部挂载到背上
SpawnWeapons定义
ShootThemUp: Components/STUWeaponComponent.h
SpawnWeapon -> SpawnWeaponsShootThemUp: Components/STUWeaponComponent.cpp
1void USTUWeaponComponent::SpawnWeapons() 2{ 3 if (!GetWorld()) return; 4 5 ACharacter *Character = Cast<ACharacter>(GetOwner()); 6 if (!Character) return; 7 8 for (auto WeaponClass : WeaponClasses) 9 { 10 auto Weapon = GetWorld()->SpawnActor<ASTUBaseWeapon>(WeaponClass); 11 if (!Weapon) return; 12 Weapons.Add(Weapon); 13 Weapon->SetOwner(Character); 14 AttachWeaponToSocket(Weapon, Character->GetMesh(), WeaponArmorySocketName); 15 } 16}
在BeginPlay中调用
ShootThemUp: Components/STUWeaponComponent.cpp
装载武器
添加数据成员: 保存当前武器标号
private
和CurrentWeapon相对应
ShootThemUp: Components/STUWeaponComponent.h
1int32 CurrentWeaponIndex = 0;
EquipWeapon定义
ShootThemUp: Components/STUWeaponComponent.h
private
1void EquipWeapon(int32 WeaponIndex);
ShootThemUp: Components/STUWeaponComponent.cpp
设置CurrentWeapon指针, 将武器挂载到WeaponEquipSocketName
1void USTUWeaponComponent::EquipWeapon(int32 WeaponIndex) 2{ 3 ACharacter *Character = Cast<ACharacter>(GetOwner()); 4 if (!Character) return; 5 6 if (CurrentWeapon) 7 { 8 AttachWeaponToSocket(CurrentWeapon, Character->GetMesh(), WeaponArmorySocketName); 9 } 10 11 CurrentWeapon = Weapons[WeaponIndex]; 12 AttachWeaponToSocket(CurrentWeapon, Character->GetMesh(), WeaponEquipSocketName); 13}
动态生成武器后, 需装载武器
ShootThemUp: Components/STUWeaponComponent.cpp
1// BeginPlay 2 3CurrentWeaponIndex = 0; 4EquipWeapon(CurrentWeaponIndex);
实现切换武器回调函数
ShootThemUp: Components/STUWeaponComponent.cpp
1void USTUWeaponComponent::NextWeapon() 2{ 3 CurrentWeaponIndex = (1 + CurrentWeaponIndex) % Weapons.Num(); 4 EquipWeapon(CurrentWeaponIndex); 5}
查看
-
设置游戏角色武器类属性数组
-
武器切换和使用正常
游戏角色死亡时, 销毁武器
- 对游戏角色调用Destroy, 会对游戏角色调用EndPlay
- 先调用组件的EndPlay, 再对游戏角色调用EndPlay
- 覆写EndPlay, 销毁武器Actor
ShootThemUp: Components/STUWeaponComponent.h
protected
1virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
ShootThemUp: Components/STUWeaponComponent.cpp
1void USTUWeaponComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) 2{ 3 CurrentWeapon = nullptr; 4 for (auto Weapon : Weapons) 5 { 6 // 卸载Actor的网格体, 与AttachToComponent相反 7 Weapon->DetachFromActor(FDetachmentTransformRules::KeepWorldTransform); // 此处是静态结构体, 不是枚举成员 8 9 // 销毁Actor 10 Weapon->Destroy(); 11 } 12 Weapons.Empty(); // 清空数组 13 14 // 也可以关闭武器的物理碰撞, 将武器保留在关卡, 几秒钟后销毁武器 15 Super::EndPlay(EndPlayReason); 16}
处理Rifle开火定时器
切换武器时, 关闭定时器
ShootThemUp: Components/STUWeaponComponent.cpp
1// EquipWeapon 2 3 if (CurrentWeapon) 4 { 5 // 其他处理 6 CurrentWeapon->FireStop(); 7 }
游戏角色死亡后, 关闭定时器
ShootThemUp: Player/STUBaseCharacter.cpp
1// OnDeath 2WeaponComponent->FireStop();