Files
MM/AGENTS.md
不明不惑 266e817771 feat(M1): project skeleton - character base, ASC, AttributeSet, Enhanced Input
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.
2026-05-02 06:32:46 +08:00

8.4 KiB
Raw Permalink Blame History

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(接口)
  • 文件名:与类名一致。UInventoryComponentInventoryComponent.h/.cpp
  • 方法PascalCase。GetHealth() ApplyDamage()
  • 成员变量PascalCase + 前缀。float MaxHealthbool 用 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++ UMGUUserWidget 派生类 + UWidgetTree 代码构建)
  • 不要创建蓝图类来继承 C++ 类,除非用户明确要求
  • 不要依赖编辑器中的蓝图节点、事件图表、变量面板
  • 不要要求用户"在编辑器中手动拖拽/配置/设置"
  • 不要用蓝图实现核心逻辑再让 C++ 调用

理由:项目由 AI 编码管线驱动Codex CLICodex 无法操作 UE 编辑器。所有可执行变更必须通过 C++ 代码文件表达。

不要做的事

  • 不要修改 MM.Build.cs 中的 PCH 设置
  • 不要在头文件中写内联实现(简单的 getter/setter 除外)
  • 不要使用 Tick 除非绝对必要,如果需要必须说明理由
  • 不要在构造函数中做复杂逻辑,放 BeginPlayInitialize
  • 不要硬编码路径、魔法数字,使用常量或 UPROPERTY(EditAnywhere) 配置
  • 不要使用 GEngine->AddOnScreenDebugMessage 在正式代码中
  • 不要在 Component 中直接依赖特定的 Actor 类型,使用接口解耦
  • 不要创建新的 UE 模块(除非明确要求),所有代码放 MM 模块
  • 不要在输出中包含"请在编辑器中手动配置"等步骤

需要修改 Build.cs 的情况

如果新代码依赖了额外的引擎模块(如 Slate, UMG, AIModule, NavigationSystem 必须同步修改 Source/MM/MM.Build.cs,在对应的 PublicDependencyModuleNamesPrivateDependencyModuleNames 中添加模块名。

构建依赖

当前已添加的模块:

  • 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