给游戏角色装载武器
2023年6月11日 2025年5月20日
概览
- 导入武器相关资产
- 创建武器类STUBaseWeapon和BP_STUBaseWeapon
- 为STUBaseWeapon添加骨骼网格体, 绑定武器模型
武器模型 说明 Launcher 发射导弹 Rifle 发射子弹 Shoot Regular Cartridges
- 为游戏角色骨骼网格体添加挂载点, 动态创建武器对象并挂载到游戏角色
导入武器相关资产
虚幻编辑器
- 之前将资产导入到Content/ExternalContent/Animation, 有两点需注意
- 资产之前存在相互引用, 这个在Migrate过程中, 不一定会全无问题
- 我们选择Migrate
ShooterGame/Content/Animations/TTP_Animations
, 而实际导出有多个文件夹, 里面的内容都和TTP_Animations有关
- 资产之前存在相互引用, 这个在Migrate过程中, 不一定会全无问题
- 本节需要Migrate的武器资产, 其相关内容与之前的内容有重叠; 和之前一样, 在ExternalContent下单独创建一个文件夹, 存放本次导入资产
从ShooterGame导出
-
选中Content/Weapons > Migrate
-
相关文件存放在Characters, Environment和Weapons中
-
保存到ShootThemUp/Content
导入到ShootThemUp
- 创建ExternalContent/Weapon, 并设置文件夹颜色
- 将资产移动到ExternalContent/Weapon
创建武器类
初始化C++类: STUBaseWeapon
创建C++类: Weapon/STUBaseWeapon
虚幻编辑器
-
Actor
-
公有类
设置头文件路径
C++
ShootThemUp: ShootThemUp.Build.cs
1PublicIncludePaths.AddRange(new string[] 2{ 3 "ShootThemUp/Public/Player", 4 "ShootThemUp/Public/Components", 5 "ShootThemUp/Public/Dev", 6 "ShootThemUp/Public/Weapon" 7});
调整框架
C++
- | |
---|---|
构造函数 | 每帧调用置为false |
Tick | 屏蔽 |
BeginPlay | - |
ShootThemUp: Weapon/STUBaseWeapon.h
ShootThemUp: Weapon/STUBaseWeapon.cpp
添加骨骼网格体组件, 用来绑定武器模型
C++
- 添加组件
protected
ShootThemUp: Weapon/STUBaseWeapon.h
1class USkeletalMeshComponent; 2 3UPROPERTY(VisibleAnywhere, BlueprintReadWrite) 4USkeletalMeshComponent *WeaponMeshComponent;
- 初始化组件
ShootThemUp: Weapon/STUBaseWeapon.cpp
1// 构造函数 2 3WeaponMeshComponent = CreateDefaultSubobject<USkeletalMeshComponent>("WeaponMeshComponent"); 4SetRootComponent(WeaponMeshComponent);
创建BP_STUBaseWeapon并绑定武器模型
虚幻编辑器
-
创建文件夹: Content/Weapon
-
创建BP_STUBaseWeapon, 保存到Content/Weapon
-
为WeaponMeshComponent绑定Rifle
-
因为武器很小, 设置Camera Speed为1
将Actor附加到可变换组件的挂载点
虚幻编辑器
文档
说明
通过AActor::AttachToComponent将Actor附加到可变换组件的挂载点上, 要求已在组件上添加挂载点, 并提供以下信息
- |
---|
Actor |
可变换组件 |
挂载规则 |
挂载点名称 |
挂载函数 AActor::AttachToComponent
可变换组件: USceneComponent及其派生类
基类 | |
---|---|
UPrimitiveComponent | USceneComponent |
UMeshComponent | UPrimitiveComponent |
USkeletalMeshComponent | UMeshComponent |
UStaticMeshComponent | UMeshComponent |
挂载规则: FAttachmentTransformRules对象
FAttachmentTransformRules
-
说明
UE_5.1/Engine/Source/Runtime/Engine/Classes/Engine/EngineTypes.h
如何计算附加Actor的变换属性
-
数据成员
-
LocationRule, RotationRule和ScaleRule
- 对应变换属性的三个分量
- 使用EAttachmentRule进行设置
- 对应变换属性的三个分量
-
bInWeldSimulatedBodies
Whether to weld simulated bodies together when attaching
不知道效果, 设为false
-
-
构造函数
- 对变换属性的分量应用相同规则
1FAttachmentTransformRules(EAttachmentRule InRule, bool bInWeldSimulatedBodies) 2 : LocationRule(InRule) 3 , RotationRule(InRule) 4 , ScaleRule(InRule) 5 , bWeldSimulatedBodies(bInWeldSimulatedBodies) 6{}
- 为变换属性定制规则
1FAttachmentTransformRules(EAttachmentRule InLocationRule, EAttachmentRule InRotationRule, EAttachmentRule InScaleRule, bool bInWeldSimulatedBodies) 2 : LocationRule(InLocationRule) 3 , RotationRule(InRotationRule) 4 , ScaleRule(InScaleRule) 5 , bWeldSimulatedBodies(bInWeldSimulatedBodies) 6{}
- 对变换属性的分量应用相同规则
EAttachmentRule
-
说明
UE_5.1/Engine/Source/Runtime/Engine/Classes/Engine/EngineTypes.h
如何计算附件Actor的最终变换矩阵
API
-
枚举成员
- SnapToTarget Snaps transform to the attach point
KeepWorld Automatically calculates the relative transform such that the attached component maintains the same world transform
KeepRelative Keeps current relative transform as the relative transform to the new parent
不知道区别, 使用SnapToTarget; 使用KeepRelative可以达到一样的效果
为骨骼网格体添加挂载点
说明
- | |
---|---|
骨骼网格体 | HeroTPP: Content/ExternalContent/Animation/Characters/HeroTPP/HeroTPP.uasset |
挂载点上级骨骼 | b_Right_Weapon |
挂载点名称 | WeaponSocket |
Socket
骨骼网格体中的特殊物体 Object
,可以为任何骨骼添加Socket
Socket的实质是骨骼网格体中的命名变换,可以在蓝图和C++中获取
骨骼的Socket有多种用途,我们可以在Socket附加武器,用作集火点, 也可以通过Socket名称获取变换信息
在骨骼网格体上添加挂载点
-
打开HeroTPP
方法一: 双击打开
方法二: 打开BP_STUBaseCharacter, 选择SkeletalMesh组件, 去到细节面板双击HeroTPP
-
查看骨骼网格体
- 左侧骨骼树面板,选中骨骼,可以在右侧细节面板查看骨骼的相对变换
- 可以是虚拟骨骼,无图形表示,具有变换属性: 如b_RightWeapon
- 左侧骨骼树面板,选中骨骼,可以在右侧细节面板查看骨骼的相对变换
-
为骨骼添加挂载点
选中b_RightWeapon,右键 > Add Socket
-
设置挂载点参数
Details
选中Socket,在右侧细节面板设置参数- Socket Name WeaponSocket Relative Rotation X: -90
-
为挂载点添加预览模型
WeaponSocket > Add Preview Asset > Rifle
-
在多种资产中预览挂载效果
举例 - HeroTPP_Skeleton 骨骼 HeroTPP 骨骼网格体 BS_Locomotion_Run 动画资产 ABP_BaseCharacter 动画蓝图 HeroTPP_Physics 通过编辑器的选项卡, 选择资产类型
-
动画资产
-
动画蓝图
-
动态创建武器, 并附加到游戏角色骨骼网格体的挂载点
C++
添加武器类型属性, 动态创建Actor时使用
ShootThemUp: Player/STUBaseCharacter.h
protected
1class ASTUBaseWeapon; 2 3UPROPERTY(EditDefaultsOnly) 4TSubclassOf<ASTUBaseWeapon> WeaponClass;
ShootThemUp: Player/STUBaseCharacter.cpp
1#include "Weapon/STUBaseWeapon.h"
动态创建武器Actor
使用了UWorld::SpawnActor, 所以我认为应该包含;但没包含编译通过了
1#include "Engine/World.h" 2 3if (!GetWorld()) return; 4const auto Weapon = GetWorld()->SpawnActor<ASTUBaseWeapon>(WeaponClass);
将武器附加到骨骼网格体挂载点
- 获取骨骼网格体
- 将Actor附加到可变换组件的挂载点
AttachToComponent的第一个参数是USenceComponent类型, 而我们传入其派生类USkeletalMeshComponent类型, 所以需要包含Components/SkeletalMeshComponent.h
1FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, false); 2Weapon->AttachToComponent(GetMesh(), AttachmentRules, "WeaponSocket");
完整实现: SpawnWeapon
ShootThemUp: Player/STUBaseCharacter.h
private
1void SpawnWeapon();
ShootThemUp: Player/STUBaseCharacter.cpp
1#include "Engine/World.h" 2#include "Components/SkeletalMeshComponent.h" 3 4void ASTUBaseCharacter::SpawnWeapon() 5{ 6 if (!GetWorld()) return; 7 const auto Weapon = GetWorld()->SpawnActor<ASTUBaseWeapon>(WeaponClass); 8 if (!Weapon) return; 9 10 FAttachmentTransformRules AttachmentRules(EAttachmentRule::SnapToTarget, false); 11 Weapon->AttachToComponent(GetMesh(), AttachmentRules, "WeaponSocket"); 12}
- 游戏角色出现在场景中时, 创建并装载武器: 在BeginPlay中调用SpawnWeapon
查看
虚幻编辑器
-
设置武器类型: 将BP_STUBaseCharacter的WeaponClass设置为BP_STUBaseWeapon
-
效果图