M1 — Project Skeleton: - MMAbilitySystemComponent: ASC skeleton (extends UAbilitySystemComponent) - MMAttributeSet: 7 core attributes (Health/MaxHealth/Mana/MaxMana/AttackPower/DefensePower/MoveSpeed) - MMCharacterBase: character base with ASC, top-down camera, Enhanced Input binding - MMPlayerController: mouse cursor enabled for top-down view - MMGameMode: default pawn and controller class setup - SaberCharacter: Saber class entry point (empty, Phase 0) - AGENTS.md: updated build dependency list All public APIs documented with /// Doxygen comments (Chinese). Pure C++ driven, no editor dependency.
8.4 KiB
8.4 KiB
AGENTS.md — MM Project
本文件供 Codex CLI 参考,定义项目约定和约束。
项目概况
- 引擎:Unreal Engine 5.7
- 项目名:MM
- 类型:单模块 C++ Runtime 项目
- 平台:macOS 开发,目标跨平台
- 项目根:
/Volumes/Game/UE/Projects/MM
目录结构
MM/
├── Source/
│ ├── MM/ # 主模块(Runtime)
│ │ ├── MM.h / MM.cpp # 模块入口
│ │ ├── MM.Build.cs # 模块构建配置
│ │ └── ... # 所有 C++ 源码放这里
│ ├── MM.Target.cs # Runtime 构建目标
│ └── MMEditor.Target.cs # Editor 构建目标
├── Content/ # 蓝图、材质、地图等资产
│ └── AGame/Map/ # 地图
├── Config/ # 引擎和项目配置
├── Docs/ # 项目文档
├── MM.uproject # 项目描述文件
└── AGENTS.md # 本文件
编码规范
命名
- 类:PascalCase + 前缀
A(Actor)U(UObject/Component)F(结构体/非UObject类)E(枚举)I(接口) - 文件名:与类名一致。
UInventoryComponent→InventoryComponent.h/.cpp - 方法:PascalCase。
GetHealth()ApplyDamage() - 成员变量:PascalCase + 前缀。
float MaxHealth,bool 用b前缀bIsAlive - 局部变量:PascalCase。
int32 ItemCount - 参数:PascalCase。
void SetHealth(float NewHealth) - 常量:全部大写 + 下划线。
MAX_INVENTORY_SLOTS - 命名空间:不使用,UE 项目惯例
UE 宏
- 所有 UObject 派生类必须有
UCLASS()(头文件中) - 所有 UObject 派生结构体必须有
USTRUCT()(头文件中) - 需要反射的成员用
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="XXX") - 需要暴露给蓝图的函数用
UFUNCTION(BlueprintCallable, Category="XXX") - 头文件使用
#pragma once .generated.h必须是最后一个#include
C++ 风格
- 使用
TArray<>而非std::vector - 使用
TMap<>而非std::unordered_map - 使用
TSharedPtr<>/TSharedRef<>而非std::shared_ptr - 使用
FString做字符串操作,FName做标识符,FText做显示文本 - 使用 UE 的
check()/ensure()/verify()而非assert() - 日志使用
UE_LOG(LogTemp, Warning, TEXT("...")),后续会有模块级 LogCategory - 不要使用 C++ 异常,UE 不使用异常机制
文件组织
- 每个类一对
.h/.cpp文件 - 头文件放声明,cpp 文件放实现
- 前向声明优先于
#include(减少编译依赖) #include顺序:对应头文件 → 引擎头文件 → 项目头文件,每组之间空一行
架构约定
Component 分层
- 核心逻辑 → C++ ActorComponent 或 SceneComponent
- 数据配置 → DataAsset / UPROPERTY(EditAnywhere)
- 视觉/调参 → 蓝图继承 C++ 基类
核心原则:纯 C++ 驱动
本项目尽量不依赖编辑器功能,所有游戏逻辑、UI、配置、资产引用都在 C++ 中完成:
- ✅ 用 C++ 创建 Actor、Component、Subsystem、DataAsset
- ✅ 用 C++ 代码注册组件、设置默认值、绑定输入、创建 Widget
- ✅ 用
ConstructorHelpers::FObjectFinder在 C++ 中引用资产 - ✅ 用
UPROPERTY(EditAnywhere)的默认值代替编辑器手动配置 - ✅ UI 用 C++ UMG(
UUserWidget派生类 +UWidgetTree代码构建) - ❌ 不要创建蓝图类来继承 C++ 类,除非用户明确要求
- ❌ 不要依赖编辑器中的蓝图节点、事件图表、变量面板
- ❌ 不要要求用户"在编辑器中手动拖拽/配置/设置"
- ❌ 不要用蓝图实现核心逻辑再让 C++ 调用
理由:项目由 AI 编码管线驱动(Codex CLI),Codex 无法操作 UE 编辑器。所有可执行变更必须通过 C++ 代码文件表达。
不要做的事
- ❌ 不要修改
MM.Build.cs中的 PCH 设置 - ❌ 不要在头文件中写内联实现(简单的 getter/setter 除外)
- ❌ 不要使用
Tick除非绝对必要,如果需要必须说明理由 - ❌ 不要在构造函数中做复杂逻辑,放
BeginPlay或Initialize - ❌ 不要硬编码路径、魔法数字,使用常量或
UPROPERTY(EditAnywhere)配置 - ❌ 不要使用
GEngine->AddOnScreenDebugMessage在正式代码中 - ❌ 不要在 Component 中直接依赖特定的 Actor 类型,使用接口解耦
- ❌ 不要创建新的 UE 模块(除非明确要求),所有代码放 MM 模块
- ❌ 不要在输出中包含"请在编辑器中手动配置"等步骤
需要修改 Build.cs 的情况
如果新代码依赖了额外的引擎模块(如 Slate, UMG, AIModule, NavigationSystem),
必须同步修改 Source/MM/MM.Build.cs,在对应的 PublicDependencyModuleNames 或 PrivateDependencyModuleNames 中添加模块名。
构建依赖
当前已添加的模块:
- Core, CoreUObject, Engine, InputCore, EnhancedInput, GameplayAbilities, GameplayTags, GameplayTasks
如果需要 UI:取消注释 Slate/SlateCore 如果需要网络:添加 OnlineSubsystem
注释规范
风格:Doxygen /// + Markdown
本项目使用 Doxygen 兼容的 /// 注释,配合 Markdown 语法生成文档站(doxygen-awesome-css 主题)。
类注释
/// 管理玩家背包物品的存储和操作。
///
/// 提供增删查改接口,支持堆叠合并和溢出计算。
///
/// # 使用示例
///
/// ```cpp
/// auto* Inv = Player->FindComponentByClass<UInventoryComponent>();
/// int32 Overflow = Inv->AddItem(FName("Potion"), 5);
/// ```
///
/// - Note: 该组件不负责 UI 渲染,仅处理数据层。
/// - SeeAlso: UItemDefinition
UCLASS()
class UInventoryComponent : public UActorComponent
函数注释
/// 向背包添加指定数量的物品。
///
/// 如果目标物品已存在,会尝试堆叠合并。
/// 背包满时返回溢出数量。
///
/// - Parameter ItemId: 物品标识符,对应 DataAsset 的 ``FPrimaryAssetId``
/// - Parameter Count: 要添加的数量,必须 > 0
/// - Returns: 溢出数量,0 表示全部成功放入
/// - Complexity: O(N),N 为当前槽位数
/// - Important: 不会触发 UI 刷新,调用方需手动通知
UFUNCTION(BlueprintCallable, Category="Inventory")
int32 AddItem(FName ItemId, int32 Count);
成员变量注释
/// 背包最大槽位数。
///
/// 默认 30,可在实例上通过 EditAnywhere 覆盖。
///
/// - Important: 运行时修改此值不会自动扩缩 ``Items`` 数组,
/// 需调用 ``ResizeSlots()`` 手动处理。
UPROPERTY(EditAnywhere, Category="Inventory")
int32 MaxSlots = 30;
结构体/枚举注释
/// 描述背包中单个物品的堆叠信息。
///
/// | 字段 | 说明 |
/// |------|------|
/// | ItemId | 物品唯一标识 |
/// | Count | 当前堆叠数量 |
USTRUCT(BlueprintType)
struct FItemStack
{
GENERATED_BODY()
/// 物品唯一标识,对应 ``UItemDefinition::ItemId``。
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FName ItemId;
/// 当前堆叠数量,范围 [1, MaxStack]。
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 Count = 0;
};
注释规则
- 每个公开的类、结构体、枚举、函数、属性都必须有
///注释 - 使用 Markdown 语法增强可读性:标题、列表、表格、代码块、粗体
- 使用标准标注:
- Parameter、- Returns、- Note、- Important、- Warning、- SeeAlso、- Complexity - 用
`` 反引号引用代码符号(类名、函数名、变量名) - 注释中的代码示例用 triple-backtick 代码块
- 注释语言用中文(因为这是面向团队的文档站)
- 实现细节放在
.cpp中用//行注释(不进入文档站)
不要做的事
- ❌ 不要用
/** */块注释,统一用/// - ❌ 不要在注释中写无意义的内容(如 "constructor" "destructor")
- ❌ 不要在
.cpp的实现中写///Doxygen 注释(只在.h中写) - ❌ 不要省略公开 API 的注释,即使是看似简单的 getter/setter
新增文件检查清单
每次新增 C++ 文件后确认:
- 文件名与主类名一致
- 包含
#pragma once(头文件) - 包含正确的 UE 宏(UCLASS/USTRUCT/UENUM)
- 包含
.generated.h(且为最后一个 include) - 遵循命名前缀规范
- 如果引入新模块依赖,已更新 MM.Build.cs