01-项目基础
01 项目基础
返回:[[00-课程索引]] 下一章:[[02-英雄角色与基础框架]]
[!info] 资料口径
代码内容按课程作者公开的WarriorRPG提交历史与最终源码交叉核对。P1、P4 是概念课,没有独立代码提交;示例使用项目后续真实代码说明概念,不代表这些代码在该视频中已经实现。
本章架构目标
- 建立 UE C++ 项目的
Target → Module → Source结构。 - 使用独立功能测试地图,降低后续输入、动画、GAS 和 AI 的验证成本。
- 理解硬引用、软引用和同步/异步加载的取舍。
P1 Introduction(05:58)
类型:课程介绍;没有独立代码提交。
技术路线
1 | Enhanced Input → Gameplay Tag → ASC → Gameplay Ability |
- C++ 负责稳定的类型、组件、算法和生命周期。
- Blueprint/Data Asset 负责能力编排、动画资产、数值和表现配置。
- GAS 是战斗系统中枢:能力、效果、属性、状态 Tag 和 Gameplay Cue 都围绕 ASC 协作。
学习检查
- 能说明
Character、Controller、AnimInstance、ASC的边界。 - 能区分数值逻辑、状态逻辑和表现逻辑。
P2 Create a New C++ Project(03:31)
提交依据:f461369 Initial commit;fde5c56 Inital Commite Done 只补充 .vsconfig。
工程关键文件
| 文件 | 职责 |
|---|---|
Warrior.uproject |
项目版本、运行时模块和插件声明 |
Source/Warrior.Target.cs |
Game Target |
Source/WarriorEditor.Target.cs |
Editor Target |
Source/Warrior/Warrior.Build.cs |
Warrior 模块编译依赖 |
Source/Warrior/Warrior.cpp |
主模块注册入口 |
Source/Warrior/Warrior.h |
模块公共基础头文件 |
主模块入口
1 | IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, Warrior, "Warrior"); |
FDefaultGameModuleImpl:使用默认游戏模块实现。Warrior:C++ 模块标识,决定WARRIOR_API导出宏名称。"Warrior":模块字符串名称,必须与.uproject、Build.cs对应。
Target 与 Module
1 | // Warrior.Target.cs |
1 | Target |
Build.cs 原则
课程最终项目会逐步加入:
GameplayTags:原生 Gameplay Tag。EnhancedInput:Input Action/Mapping Context。GameplayTasks、Gameplay Abilities 插件:GAS。AnimGraphRuntime:动画运行时工具。MotionWarping:攻击 Root Motion 对齐。Niagara:投射物和溶解特效。NavigationSystem:AI 导航。
[!warning] 不要把最终依赖列表误认为 P2 一次性加入。每引入一个模块公开类型,再补充对应依赖,能更清楚地理解模块边界。
Git 与生成目录
1 | 提交:Source、Config、Content、.uproject |
Content/** 是二进制资产,课程仓库使用 Git LFS 管理。项目文件和解决方案可重新生成,不应把编译产物当源码提交。
验收
-
Development Editor能编译并启动。 - 知道
XXX_API来自模块名,而不是项目显示名称。 - 知道
Target.cs与Build.cs解决的是不同问题。
P3 Set Up Test Map(03:24)
提交依据:99adefa TestMapCreated。
资产和配置
- 新建:
Content/Maps/FeatureDevMap.umap。 - 同步产生
Content/__ExternalActors__/Maps/FeatureDevMap/...与__ExternalObjects__。 - 修改:
Config/DefaultEngine.ini、Config/DefaultInput.ini。
地图引用路径:
1 | /Game/Maps/FeatureDevMap.FeatureDevMap |
为什么建立 FeatureDevMap
- 将底层功能测试与正式关卡隔离。
- 保持地面、光照、PlayerStart、NavMesh 等环境可重复。
- 缩短启动和复现问题的时间。
- 后续能逐项验证相机、动画、武器、敌人和 GAS,而不被大型场景干扰。
UE5 External Actors
开启 One File Per Actor/World Partition 后,一个地图修改可能同时变更:
1 | FeatureDevMap.umap |
这些文件应由编辑器管理,不能手工移动散列目录。提交地图时要把相关 External Actor 一并提交。
地图配置的区别
GameDefaultMap:普通游戏启动时打开。EditorStartupMap:编辑器启动后打开。GlobalDefaultGameMode:地图未覆盖 GameMode 时使用。
[!note] 最终仓库的
EditorStartupMap后来改为生存模式测试地图;P3 创建和使用的是FeatureDevMap。
验收
- PIE 后角色从有效 PlayerStart 生成。
- 地面碰撞、光照和输入环境稳定。
- Git 变更包含地图对应的 External Actor 文件。
P4 Hard and Soft Reference(10:33)
类型:概念课;没有独立提交。以下示例来自本课程后续真实源码。
硬引用
1 | UPROPERTY(EditDefaultsOnly) |
- 对象硬引用通常是
UObject*/TObjectPtr<T>。 - 类硬引用通常是
TSubclassOf<T>/UClass*。 - 优点:对象已加载时直接使用,代码简单。
- 代价:会扩大资产依赖图;宿主加载可能把引用链一起带入内存。
软对象引用
课程后续角色启动数据:
1 | UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "CharacterData") |
同步加载流程:
1 | if (!CharacterStartUpData.IsNull()) |
IsNull():检查是否配置软路径。LoadSynchronous():阻塞加载并返回对象。Get():只取得已加载对象,不保证主动加载成功。
软类引用与异步加载
课程后续生存模式使用:
课程最终源码将软类引用放在每波敌人配置中:
1 | struct FWarriorEnemyWaveSpawnerInfo |
1 | UAssetManager::GetStreamableManager().RequestAsyncLoad( |
典型流程:
1 | 软路径 → RequestAsyncLoad → 回调 → Get() → 缓存 UClass* → SpawnActor |
选择表
| 场景 | 建议 |
|---|---|
| 常驻、体积小、创建时必需 | 硬引用 |
| 地图、大型角色、敌人类型、可选 UI/特效 | 软引用 |
| 当前帧必须得到且资源很小 | LoadSynchronous() |
| 大型资源或批量生成 | RequestAsyncLoad() |
[!warning] 软引用不是无成本方案。它引入加载状态、回调生命周期、失败处理和缓存管理;不要机械地把所有硬引用改成软引用。
验收
- 能在 Reference Viewer 中识别硬依赖链。
- 能解释
TSoftObjectPtr与TSoftClassPtr的区别。 - 能解释
Get()、LoadSynchronous()与RequestAsyncLoad()的行为差异。
本章复盘
- 理解
Target → Module → Source。 - 能独立创建并配置功能测试地图。
- 知道 External Actor 为什么必须一起提交。
- 能根据资源大小和使用时机选择硬/软引用。
本文从 LearnByCompany 原始文档 自动同步。
