02-英雄角色与基础框架
02 英雄角色与基础框架
上一章:[[01-项目基础]] 返回:[[00-课程索引]] 下一章:[[03-近战连招系统]]
[!info] 阅读说明
每节包含课程对应的实际类/函数或资产职责。Content/*.uasset为二进制,笔记只记录提交历史可以确认的资产关系,不虚构蓝图内部节点。
本章最终调用链
1 | BP_BaseGameMode |
P5 Set Up Hero Character Section Overview(00:46)
类型:章节概览,无独立代码提交。
- 类结构:GameMode、BaseCharacter、HeroCharacter、HeroController。
- 输入:Gameplay Tag 驱动的 Enhanced Input。
- 动画:通用 AnimInstance + Hero AnimInstance + AnimBP。
- GAS:ASC、AttributeSet、Gameplay Ability 激活策略。
- 数据:Startup Data 软引用与武器配置。
P6 Basic Class Structure(07:10)
提交:4705f83 BaseClassesCreated。
类层级
1 | AGameModeBase → AWarriorBaseGameMode → BP_BaseGameMode |
关键文件:
Public/Characters/WarriorBaseCharacter.hPublic/Characters/WarriorHeroCharacter.hPublic/Controllers/WarriorHeroController.hPublic/GameModes/WarriorBaseGameMode.h
角色构造中的基础设置:
1 | PrimaryActorTick.bCanEverTick = false; |
DefaultEngine.ini 通过 GlobalDefaultGameMode 指向 BP_BaseGameMode,再由 GameMode 蓝图选择 Hero Pawn 和 Hero Controller。
设计重点:公共能力放 Base,玩家专属行为放 Hero;蓝图负责选择 Mesh、AnimBP 和默认类。
P7 Debug Helper(04:54)
提交:ead75ab Debug helper created。
文件:Public/WarriorDebugHelper.h。
1 | namespace Debug |
调用链:
1 | Debug::Print |
InKey=-1每次新增消息;固定 Key 可刷新同一条消息。- 屏幕输出用于即时观察,日志用于保存和检索,断点用于检查调用栈与内存。
- 头文件
static函数具有内部链接;适合简单工具,但大型项目更推荐独立 Log Category。
P8 Set Up Hero Camera(09:52)
提交:22978e6 CameraDone。
字段:
1 | USpringArmComponent* CameraBoom; |
构造逻辑:
1 | CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom")); |
旋转职责:
1 | Controller Rotation → SpringArm → Camera |
因此相机跟随控制器,角色不直接跟随控制器 Yaw,而是自然朝向移动方向。
P9 Native Gameplay Tags(09:37)
提交:a74dc12 NativeTagsDone。
文件:WarriorGameplayTags.h/.cpp。
1 | namespace WarriorGameplayTags |
1 | UE_DEFINE_GAMEPLAY_TAG(InputTag_Move, "InputTag.Move"); |
- C++ 标识符和 Tag 字符串是两层概念。
MatchesTag支持父子层级;MatchesTagExact/HasTagExact要求精确。GameplayTags必须进入模块依赖。
[!warning]
UE_DECLARE_GAMEPLAY_TAG_EXTERN的导出写法要以当前 UE5.4 宏定义与模块编译结果为准。声明、定义的命名空间和符号名必须完全一致;链接错误首先检查.cpp是否编入当前模块,而不是只修改 Tag 字符串。
P10 Input Config Data Asset(10:30)
提交:f5b4a2a InputConfigDone。
课程公开最终源码原文:
1 | USTRUCT(BlueprintType) |
建议修正版应显式写成 UInputAction* InputAction = nullptr;,否则 UE 结构体反射检查可能报告对象属性未初始化;用户本地工程目前就存在过这一日志错误。
1 | UCLASS() |
查找算法遍历 NativeInputActions,同时检查 Tag 相等和 Action 非空。资产配置:
1 | DA_InputConfig |
[!bug] 用户当前工程中的
InputAction若未初始化为nullptr,UE 会产生ObjectProperty ... is not initialized properly。结构体对象指针必须显式默认初始化。
P11 Custom Enhanced Input Component(07:24)
提交:69488a7 Custom input component done。
1 | UCLASS() |
核心模板:
1 | template<class UserObject, typename CallbackFunc> |
DefaultInput.ini:
1 | DefaultPlayerInputClass=/Script/EnhancedInput.EnhancedPlayerInput |
这是后续 CastChecked<UWarriorInputComponent> 成立的前提。
P12 Binding Input(15:43)
提交:ef005ac Input binding done。
SetupPlayerInputComponent:
1 | 检查 InputConfigDataAsset |
移动实现只采用控制器 Yaw:
1 | const FVector2D InputVector = InputActionValue.Get<FVector2D>(); |
视角:
1 | AddControllerYawInput(InputVector.X); |
[!warning] 当前用户工程应对
Controller、LocalPlayer、InputConfigDataAsset做空值保护;课程代码大量使用check/checkf,适合开发期暴露配置错误,但 Shipping 行为和崩溃策略需要自行设计。
P13 Character Anim Instance(12:57)
提交:8653e2b Animinstances done。
继承:
1 | UAnimInstance |
初始化缓存:
1 | OwningCharacter = Cast<AWarriorBaseCharacter>(TryGetPawnOwner()); |
线程安全更新:
1 | GroundSpeed = OwningCharacter->GetVelocity().Size2D(); |
- 初始化阶段缓存 UObject 指针。
NativeThreadSafeUpdateAnimation只读取可安全访问的数据,不生成 Actor、不修改世界状态。- 最终源码后续又加入
LocomotionDirection,但它属于敌人 Strafing 章节。
P14 Hero AnimBP(04:42)
提交:7fd5959 HeroAnimBP done;纯资产课。
资产:
ABP_HeroBS_UnarmedLocomotionBP_HeroCharacter
数据流:
1 | Character Velocity/Acceleration |
AnimBP 的父类应为 UWarriorHeroAnimInstance,Skeletal Mesh 的 Anim Class 指向 ABP_Hero。
P15 Hero Anim Instance(09:31)
提交:e7b741d Relax state done。
课程公开最终源码保留了两处历史拼写:
1 | AWarriorHeroCharacter* OwningHeroCharacter; |
对应更新逻辑:
1 | if (bHasAcceleration) |
用户本地工程已规范化为 EnterRelaxStateThreshold 和 IdleElapsedTime = 0.f,这是推荐修正版,不是课程仓库原始拼写。
- 必须先调用
Super::NativeThreadSafeUpdateAnimation,确保bHasAcceleration已更新。 - 移动后立即重置计时和 Relax 状态。
- 原课程仓库中存在
EnterRelaxtStateThreshold、IdleElpasedTime的历史拼写;用户工程已改为规范名称。
P16 Gameplay Ability System(17:01)
提交:959f8cb GAS done。
新类:
1 | UAbilitySystemComponent → UWarriorAbilitySystemComponent |
基础角色:
1 | class AWarriorBaseCharacter : public ACharacter, public IAbilitySystemInterface |
1 | WarriorAbilitySystemComponent = CreateDefaultSubobject<UWarriorAbilitySystemComponent>(...); |
初始化:
1 | void AWarriorBaseCharacter::PossessedBy(AController* NewController) |
1 | Owner Actor = Character |
- Owner 持有能力系统状态。
- Avatar 是能力实际作用和表现的实体。
- 本课程 ASC 位于 Character,因此二者相同;若迁移到 PlayerState,二者会不同。
[!warning]
GameplayAbilities应作为直接模块依赖声明。只依赖.uproject的 AdditionalDependencies 不如Build.cs明确可靠。
P17 Ability Activation Policy(11:08)
提交:d871f47 Activation Policy done。
1 | UENUM(BlueprintType) |
UWarriorGameplayAbility 覆盖 OnGiveAbility:
1 | if (AbilityActivationPolicy == EWarriorAbilityActivationPolicy::OnGiven && |
OnGiven 能力结束后清除自身 Spec:
1 | GiveAbility → OnGiveAbility → TryActivateAbility → EndAbility → ClearAbility |
适合一次性初始化能力,例如出生时生成武器。OnTriggered 能力保留在 ASC,等待输入/事件激活。
P18 Set Up Weapon Class(08:49)
提交:cff1059 Weapon class created。
1 | AActor |
组件:
1 | UStaticMeshComponent* WeaponMesh; |
构造:
1 | PrimaryActorTick.bCanEverTick = false; |
本节只搭 Weapon Actor 骨架。命中委托、Overlap 和伤害逻辑属于后续 P58-P60。
P19 Set Up Hero Weapon(08:34)
提交:52b3a04 Set up hero weapon done;主要是蓝图/资产配置。
资产:
BP_HeroWeaponBaseBP_HeroAxeGA_Shared_SpawnWeaponGA_Hero_SpawnAxe
职责:
1 | GA_Hero_SpawnAxe |
武器碰撞默认关闭;Socket 和相对 Transform 在 Skeleton/蓝图中配置,C++ 不硬编码具体美术偏移。
P20 Start Up Data(12:15)
提交依据:启动数据类型与 P21 的同步加载在 d1883dd Sync loading done 中共同落地;B站将概念拆成两集。
类型:
1 | UDataAsset |
核心字段:
1 | // 授予后按 OnGiven 策略自动执行,例如生成武器 |
GiveToAbilitySystemComponent 会依次调用 GrantAbilities 授予这两组能力;后续受击与死亡链依赖 ReactiveAbilities,不能只配置第一组。
核心函数:
1 | virtual void GiveToAbilitySystemComponent(UWarriorAbilitySystemComponent* InASCToGive, |
授予:
1 | FGameplayAbilitySpec AbilitySpec(Ability); |
DA_Hero 配置出生时的 OnGiven 能力,例如生成斧头。
P21 Synchronous Loading(13:10)
提交:d1883dd Sync loading done。
角色字段:
1 | TSoftObjectPtr<UDataAsset_StartUpDataBase> CharacterStartUpData; |
英雄初始化:
1 | if (!CharacterStartUpData.IsNull()) |
完整链:
1 | Controller Possess Hero |
同步加载简单、顺序明确,但会阻塞游戏线程。单个英雄出生数据可以接受;大量敌人生成时课程后续改用异步加载。
P22 Section Wrap Up(01:42)
类型:总结课,无独立提交。
本章完成:
1 | 类层级 + 相机 |
尚未完成:武器注册、武器能力授予/撤销、轻重攻击连招、实际伤害。
本章源码检查清单
-
FWarriorInputActionConfig::InputAction初始化为nullptr。 - 动画实例初始化和更新调用
Super。 - ASC 在授予能力前执行
InitAbilityActorInfo。 -
GameplayAbilities作为直接模块依赖。 - 非 Editor 构建中不要调用
AActor::GetActorLabel()。 - Startup Data 只在正确生命周期加载一次。
本文从 LearnByCompany 原始文档 自动同步。
