在 Unity 项目里使用 Claude Code、Codex、Cursor 这类编码代理时，效果好坏并不只取决于模型有多聪明。更关键的是：你的工程是否给代理提供了足够清晰的 **affordances（可供性）**。

也就是说，仓库结构、命名、测试、静态检查、编辑器脚本、CI 和文档，是否让代理很容易看懂：

- 应该在哪里改代码
- 哪些代码不能碰
- 改完以后如何验证
- 哪些规则违反后必须修复
- 什么时候需要更新文档、Prefab、场景或 ScriptableObject

Unity 项目尤其需要这些护栏。因为 Unity 的状态不只存在于 `.cs` 文件里，还存在于 `.unity` 场景、`.prefab`、`.asset`、`.asmdef`、Project Settings、Addressables 配置、Input Actions、Animator Controller 等资产里。代理如果只把仓库当成一堆 C# 文件，很容易生成能编译但不可维护、不可运行，甚至破坏序列化引用的代码。

一个适合代理协作的 Unity 仓库，应该被视为代理的 **execution environment**，而不是单纯的源码目录。好的 Unity vibe coding 环境应该提供：

- 快速验证“坏工程”的脚本
- 明确的代码边界和 Assembly Definition
- 提交前强制执行的格式、编译、测试检查
- 代理能自检的一个统一验证命令
- 能解释场景、Prefab、资源管线和架构约束的文档

## 让 Unity 仓库对代理可读

Unity 项目的默认 `Assets/` 很容易变成混乱的资源池。为了让编码代理稳定工作，项目结构需要比普通人类团队更明确。

推荐结构：

```plaintext
Assets/
  _Project/
    Art/
    Audio/
    Configs/
      GameBalance/
      Addressables/
    Prefabs/
      UI/
      Gameplay/
      Systems/
    Scenes/
      Boot.unity
      MainMenu.unity
      Gameplay.unity
    Scripts/
      Runtime/
        Core/
        Gameplay/
        UI/
        Infrastructure/
      Editor/
      Tests/
        EditMode/
        PlayMode/
    ScriptableObjects/
    Shaders/
    UI/
  ThirdParty/
  Plugins/
Packages/
ProjectSettings/
UserSettings/              # usually ignored
.agents/
  skills/
AGENTS.md
README.md
docs/
  architecture.md
  conventions.md
  asset-pipeline.md
  testing.md
  scenes-and-entrypoints.md
  build-and-release.md
  performance.md
  cleanup.md
```

核心原则：

- 所有自研内容放在 `Assets/_Project/`，第三方资产放在 `Assets/ThirdParty/` 或 `Assets/Plugins/`。
- Runtime、Editor、Tests 分离，避免编辑器代码进入玩家构建。
- 场景入口、启动流程、全局服务、资源加载策略写进文档。
- Prefab、ScriptableObject、Addressables 不要只靠口口相传，必须有可读说明。
- 每个主要模块使用 `.asmdef` 限定依赖方向。

## 固定 Unity 序列化和 Git 配置

在让代理修改 Unity 项目前，先把版本控制和序列化设置固定住。否则代理即使只改一行 C#，也可能因为场景、Prefab、`.meta` 或二进制资源的差异制造难以 review 的变更。

Unity Project Settings 建议：

```plaintext
Edit > Project Settings > Version Control > Mode: Visible Meta Files
Edit > Project Settings > Editor > Asset Serialization > Mode: Force Text
```

仓库规则：

- `.meta` 文件必须提交；它们保存 GUID，是场景、Prefab、ScriptableObject 引用稳定的前提。
- 不手动编辑 `.meta`，除非任务明确涉及 GUID、资源迁移或冲突修复。
- `.unity`、`.prefab`、`.asset` 使用文本序列化，方便代理和 reviewer 看 diff。
- 大型二进制资源使用 Git LFS，避免仓库膨胀。
- 配置 UnityYAMLMerge，减少场景和 Prefab 合并冲突。

示例 `.gitignore`：

```gitignore
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
[Ll]ogs/
[Uu]ser[Ss]ettings/
.vs/
.idea/
*.user
*.pidb
*.booproj
*.svd

# Generated IDE files. Commit these only if your team intentionally relies on them.
*.csproj
*.sln
*.suo
```

示例 `.gitattributes`：

```gitattributes
*.cs text eol=lf
*.asmdef text eol=lf
*.unity text eol=lf merge=unityyamlmerge
*.prefab text eol=lf merge=unityyamlmerge
*.asset text eol=lf merge=unityyamlmerge
*.meta text eol=lf merge=unityyamlmerge
*.controller text eol=lf merge=unityyamlmerge
*.anim text eol=lf merge=unityyamlmerge
*.mat text eol=lf merge=unityyamlmerge
*.png filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.mp3 filter=lfs diff=lfs merge=lfs -text
```

UnityYAMLMerge 需要在本机或 CI runner 上配置 merge driver。路径按实际 Unity 安装位置调整：

```bash
git config merge.unityyamlmerge.name "Unity SmartMerge"

# macOS
git config merge.unityyamlmerge.driver '"/Applications/Unity/Hub/Editor/2022.3.0f1/Unity.app/Contents/Tools/UnityYAMLMerge" merge -p %O %A %B %A'

# Windows
git config merge.unityyamlmerge.driver '"C:/Program Files/Unity/Hub/Editor/2022.3.0f1/Editor/Data/Tools/UnityYAMLMerge.exe" merge -p %O %A %B %A'
```

示例 Assembly Definition 布局：

```plaintext
Assets/_Project/Scripts/Runtime/Core/Project.Core.asmdef
Assets/_Project/Scripts/Runtime/Gameplay/Project.Gameplay.asmdef
Assets/_Project/Scripts/Runtime/UI/Project.UI.asmdef
Assets/_Project/Scripts/Editor/Project.Editor.asmdef
Assets/_Project/Scripts/Tests/EditMode/Project.Tests.EditMode.asmdef
Assets/_Project/Scripts/Tests/PlayMode/Project.Tests.PlayMode.asmdef
```

建议依赖方向：

```plaintext
Project.Gameplay -> Project.Core
Project.UI       -> Project.Core
Project.Editor   -> Project.Core, Project.Gameplay, Project.UI
Tests            -> Runtime assemblies
```

禁止让 `Core` 反向依赖 `Gameplay` 或 `UI`。这类规则可以通过文档、asmdef 依赖和 CI 检查共同约束。

## 用 asmdef 控制爆炸半径

Unity 没有 TypeScript monorepo 那样天然的包边界，但 `.asmdef` 可以起到类似作用。

一个适合代理修改的 Unity 项目，不应该让所有脚本都处在默认 Assembly-CSharp 里。否则代理新增一个类时，很容易无意识引用任何地方的类型，最后形成大型循环依赖。

推荐规则：

- 每个稳定模块都有自己的 `.asmdef`。
- Runtime assembly 不引用 Editor assembly。
- Feature 模块只能依赖 Core、Shared、明确允许的服务层。
- UI 不直接调用存档、网络、支付等底层实现，而是依赖接口或应用服务。
- Editor 工具放在 `Editor/` 目录，并使用 Editor-only asmdef。

示例 `Project.Gameplay.asmdef`：

```json
{
  "name": "Project.Gameplay",
  "rootNamespace": "Project.Gameplay",
  "references": [
    "Project.Core"
  ],
  "includePlatforms": [],
  "excludePlatforms": [],
  "allowUnsafeCode": false,
  "overrideReferences": false,
  "precompiledReferences": [],
  "autoReferenced": true,
  "defineConstraints": [],
  "versionDefines": [],
  "noEngineReferences": false
}
```

`rootNamespace` 很重要。它能帮助代理遵守命名空间，不要把所有类都生成在全局空间。

## 为代理准备 Unity 专属 AGENTS.md

TypeScript 项目常用 `CLAUDE.md`，Unity 项目可以使用 `AGENTS.md`、`CLAUDE.md` 或 `.cursor/rules`。关键是让所有代理读取同一套规则。

示例：

````markdown
# Project Unity Coding Rules

## Overview

This is a Unity game built with Unity 2022.3 LTS.
Runtime code lives in `Assets/_Project/Scripts/Runtime`.
Editor tools live in `Assets/_Project/Scripts/Editor`.
Do not modify third-party assets under `Assets/ThirdParty` unless explicitly asked.

## Entry Points

- Boot scene: `Assets/_Project/Scenes/Boot.unity`
- Main menu scene: `Assets/_Project/Scenes/MainMenu.unity`
- Gameplay scene: `Assets/_Project/Scenes/Gameplay.unity`
- Game bootstrap: `Project.Core.Bootstrap.GameBootstrapper`

## Mandatory Rules

- Do not create scripts in `Assets/` root.
- Do not put project code in global namespace.
- Do not edit `.meta` files manually unless the task explicitly requires asset GUID work.
- Do not move or rename assets casually; Unity references depend on GUIDs.
- Do not modify `ProjectSettings/` unless the task is about build settings, input, quality, graphics, packages, or player settings.
- Do not modify third-party plugin code; wrap it from project code instead.
- Prefer editing existing components over adding duplicate manager classes.
- Before adding a singleton, search for existing services, installers, bootstrap code, or ScriptableObject configs.

## C# Style

- Use explicit namespaces matching assembly/module names.
- Use `private` fields with `[SerializeField]` for inspector references.
- Avoid public mutable fields.
- Avoid `FindObjectOfType`, `GameObject.Find`, and tag-based lookup in gameplay code unless there is no stable reference path.
- Avoid `async void` except Unity event handlers where unavoidable.
- Prefer cancellation-aware async flows when using UniTask or Tasks.
- Do not catch and rethrow exceptions without adding useful context.
- Do not add comments that narrate obvious code.

## Unity Lifecycle Rules

- Keep `Awake` for local initialization.
- Keep `Start` for cross-object initialization that depends on scene setup.
- Keep `Update` small; move non-trivial behavior into named methods or systems.
- Unsubscribe events in `OnDisable` or `OnDestroy` consistently with where they were subscribed.
- Do not allocate every frame in `Update`, `LateUpdate`, `FixedUpdate`, UI bindings, or hot gameplay paths.

## Validation

Before considering a task complete, run:

```bash
./tools/validate-unity.sh
```

If validation fails, fix the cause. Do not weaken tests, remove analyzers, or bypass compilation unless explicitly asked.
````

## 技能体现 Unity 最佳实践

如果团队成员使用不同代理，例如 Claude、Codex、Cursor、JetBrains AI，可以把共享技能或规则放在 `.agents/skills/`，再由各工具引用。

```plaintext
.agents/
  skills/
    unity-csharp-expert/
      SKILL.md
    unity-editor-tooling/
      SKILL.md
    unity-performance/
      SKILL.md
    unity-ui-ugui/
      SKILL.md
    unity-addressables/
      SKILL.md
.codex/
  skills/
    unity-csharp-expert -> ../../.agents/skills/unity-csharp-expert
.claude/
  skills/
    unity-csharp-expert -> ../../.agents/skills/unity-csharp-expert
```

完整 Skill 模板见附录 A。最小化版本至少要覆盖：

- 修改前读取 `AGENTS.md`、相关 `docs/*.md` 和最近的 `.asmdef`。
- 保护 Unity 序列化字段、Prefab、Scene、ScriptableObject 和 `.meta`。
- 限制 Runtime / Editor 依赖边界。
- 对性能、UI、Addressables 等高风险领域使用专门 Skill。
- 完成前说明验证结果和资产影响。

Unity 的关键区别是：**C# 类型重构会影响序列化数据**。代理必须知道，字段改名、类改名、命名空间改名、文件移动、asmdef 变更，都可能破坏场景和 Prefab 引用。

## 附录 A：完整 Skills 模板

下面是上文出现的 `.agents/skills/*/SKILL.md` 可直接落地版本。实际使用时，把 `Project`、路径和技术栈替换成项目真实名称。

### `.agents/skills/unity-csharp-expert/SKILL.md`

````markdown
---
name: unity-csharp-expert
description: Use when writing, reviewing, or refactoring Unity runtime C# code, especially MonoBehaviours, ScriptableObjects, gameplay systems, services, asmdefs, serialized fields, async flows, and tests.
---

# Unity C# Expert

Use this skill when editing Unity runtime C# code.

## Read First

- `AGENTS.md`
- `docs/architecture.md`
- `docs/conventions.md`
- `docs/scenes-and-entrypoints.md`
- `docs/asset-pipeline.md`
- The nearest `.asmdef` for the files being changed

## Core Rules

- Check existing MonoBehaviours, ScriptableObjects, services, bootstrap code, tests, and asmdefs before creating new files.
- Preserve serialized field names unless a migration is included.
- Do not rename serialized fields without `[FormerlySerializedAs]` and a migration note.
- Do not move or rename `.unity`, `.prefab`, `.asset`, or `.meta` files unless explicitly asked.
- Do not create scripts in `Assets/` root or global namespace.
- Do not modify third-party assets; wrap them from project code.
- Keep changes surgical. Do not redesign architecture around a small feature or bug fix.

## C# Style

- Use namespaces that match the owning assembly or feature area.
- Use `private` fields with `[SerializeField]` for inspector references.
- Avoid public mutable fields.
- Prefer explicit dependencies over scene-wide lookup.
- Avoid single-use helpers, wrappers, base classes, and manager classes.
- Avoid comments that narrate obvious code; comment only hidden constraints or surprising Unity behavior.

## Unity Runtime Rules

- Use `Awake` for local initialization and `Start` for initialization that depends on scene wiring.
- Subscribe and unsubscribe events symmetrically, usually in `OnEnable` and `OnDisable`.
- Keep `Update`, `LateUpdate`, and `FixedUpdate` small and allocation-free.
- Avoid `FindObjectOfType`, `GameObject.Find`, tag lookups, and broad singleton lookup in gameplay code.
- Avoid per-frame LINQ, string formatting, closure allocations, and repeated `GetComponent` in hot paths.
- Validate serialized references in `OnValidate`, targeted editor validation, or startup validation.

## Async And Coroutines

- Avoid `async void` except Unity event handlers where unavoidable.
- Prefer cancellation-aware async flows when using UniTask or `Task`.
- Stop coroutines or cancel async work when objects are disabled or destroyed.
- Do not update destroyed Unity objects after awaits, scene unloads, or cancellation.

## Tests And Validation

- Add or update EditMode tests for pure logic, ScriptableObject constraints, and editor validation.
- Add or update PlayMode tests for scene loading, lifecycle, UI, and gameplay flows.
- Before finishing, run `./tools/validate-unity.sh` when Unity is available.
- If validation fails, fix the cause rather than bypassing checks.

## Final Response Checklist

- Mention any serialized field, asset, scene, prefab, or asmdef impact.
- Mention tests run and validation status.
- Mention if Unity was unavailable and which checks remain for the user.
````

### `.agents/skills/unity-editor-tooling/SKILL.md`

````markdown
---
name: unity-editor-tooling
description: Use when creating or changing Unity Editor scripts, custom inspectors, menu items, asset processors, validation commands, build scripts, importers, and CI-facing `-executeMethod` entry points.
---

# Unity Editor Tooling

Use this skill for code under `Assets/_Project/Scripts/Editor` and editor-only assemblies.

## Read First

- `AGENTS.md`
- `docs/asset-pipeline.md`
- `docs/build-and-release.md`
- `docs/testing.md`
- The editor `.asmdef` and the runtime assemblies it references

## Boundaries

- Editor code must be in an `Editor/` folder or an Editor-only asmdef.
- Runtime assemblies must not reference `UnityEditor`.
- Do not put editor utilities in runtime namespaces.
- Do not modify Project Settings unless the task explicitly requires it.
- Do not create editor automation that silently rewrites scenes, prefabs, or assets without a dry-run or clear log.

## Validation Commands

- Prefer static methods callable by `-executeMethod` for CI-facing validation.
- Throw `BuildFailedException` for validation failures so Unity exits non-zero in batchmode.
- Log enough asset paths and object names for agents and humans to fix failures.
- Keep validation deterministic. Do not depend on current scene selection, inspector focus, or editor window state.

## AssetDatabase Rules

- Use `AssetDatabase.FindAssets` with scoped folders, not whole-project scans by default.
- Use GUIDs and `AssetDatabase.GUIDToAssetPath` for stable asset lookup.
- Call `AssetDatabase.SaveAssets` only when the tool intentionally mutates assets.
- Do not call `AssetDatabase.Refresh` repeatedly inside loops.
- Never delete assets automatically unless the command is explicitly destructive and documented.

## Custom Inspectors And Windows

- Keep editor UI thin; put validation and transformation logic in testable helper methods.
- Support multi-object editing only when intentionally implemented.
- Use `Undo.RecordObject` or `Undo.RegisterCompleteObjectUndo` for inspector-driven mutations.
- Mark changed assets dirty only when values actually change.

## Final Response Checklist

- Mention whether the tool reads assets, mutates assets, or changes Project Settings.
- Mention the menu path or `-executeMethod` entry point.
- Mention validation run status.
````

### `.agents/skills/unity-performance/SKILL.md`

````markdown
---
name: unity-performance
description: Use when changing hot gameplay paths, Update loops, physics, UI refresh, pooling, allocations, Addressables loading, mobile performance, memory, frame time, or build size.
---

# Unity Performance

Use this skill when performance, memory, GC, frame time, loading, or build size could be affected.

## Read First

- `AGENTS.md`
- `docs/performance.md`
- `docs/architecture.md`
- Relevant profiler captures or benchmark notes if present

## Runtime Rules

- Keep per-frame code allocation-free unless the allocation is intentional and documented.
- Avoid per-frame LINQ, closures, string interpolation, boxing, and repeated component lookups.
- Cache component references when access is repeated.
- Prefer object pooling for frequently spawned short-lived objects.
- Do not add new global `Update` loops when existing systems can own the work.
- Prefer event-driven UI refresh over polling.

## Physics And Animation

- Use `FixedUpdate` for physics mutation and `Update` for input sampling.
- Avoid changing physics settings globally for a local feature.
- Do not call expensive Animator or hierarchy operations every frame without measuring.
- Be explicit about world space vs local space operations.

## Loading And Memory

- Release Addressables handles consistently with the ownership model.
- Avoid loading large assets synchronously on gameplay paths.
- Do not keep scene-only references in persistent services after scene unload.
- Avoid mutating imported ScriptableObject assets at runtime; copy runtime state when needed.

## Validation

- Add tests for logic changes, but do not pretend unit tests prove performance.
- If profiler data is available, compare before and after.
- For risky changes, document expected frame-time, allocation, memory, or loading impact.

## Final Response Checklist

- Mention hot paths touched.
- Mention expected allocation and frame-time impact.
- Mention tests run and any profiling not performed.
````

### `.agents/skills/unity-ui-ugui/SKILL.md`

````markdown
---
name: unity-ui-ugui
description: Use when editing Unity UI built with uGUI, Canvas, RectTransform, prefabs, view controllers, UI events, navigation, layout, localization, and accessibility.
---

# Unity UI uGUI

Use this skill when editing uGUI screens, prefabs, panels, widgets, and UI-facing C# code.

## Read First

- `AGENTS.md`
- `docs/architecture.md`
- `docs/asset-pipeline.md`
- `docs/scenes-and-entrypoints.md`
- Existing UI prefabs and controllers in the same feature area

## UI Code Rules

- Keep views thin. UI components bind data, raise user intents, and delegate behavior to services or presenters.
- Do not put gameplay, save, network, or economy logic directly in button handlers.
- Use serialized references for UI widgets. Avoid runtime hierarchy searches except during controlled setup.
- Subscribe and unsubscribe UI events symmetrically.
- Avoid rebuilding layouts every frame.
- Do not leave unused serialized fields, stale branches, hidden panels, or abandoned animation hooks.

## Prefab And Layout Rules

- Preserve prefab references and serialized field names.
- Do not unpack or restructure large UI prefabs unless explicitly asked.
- Prefer editing existing UI prefabs/controllers over creating parallel variants.
- Be careful with anchors, pivots, safe areas, scaling, and dynamic text length.
- Keep localization expansion in mind; avoid hard-coded widths for text-heavy UI.

## Accessibility And Input

- Preserve keyboard/controller navigation when changing selectable UI.
- Keep interactable state and visual state consistent.
- Avoid color-only state communication when the UI needs accessibility.

## Validation

- Add EditMode tests for formatting/presenter logic when possible.
- Add PlayMode tests for critical UI flows when practical.
- Run relevant scenes or validation commands when Unity is available.

## Final Response Checklist

- Mention UI prefabs, scenes, or serialized fields touched.
- Mention input/navigation impact.
- Mention tests or manual validation performed.
````

### `.agents/skills/unity-addressables/SKILL.md`

````markdown
---
name: unity-addressables
description: Use when changing Unity Addressables, remote content, asset references, labels, groups, loading/release flows, catalogs, or asset bundle build validation.
---

# Unity Addressables

Use this skill when editing Addressables configuration, code paths that load assets, or assets intended for remote/local bundles.

## Read First

- `AGENTS.md`
- `docs/asset-pipeline.md`
- `docs/build-and-release.md`
- Existing Addressables groups, labels, and key conventions

## Key And Group Rules

- Addressable keys must be stable. Do not rename keys casually.
- Do not hard-code the same key in multiple places; centralize keys in constants or config.
- Use labels intentionally. Do not add broad labels that pull too many assets into memory.
- Keep group schema, compression, remote/local settings, and update restrictions consistent with existing groups.
- Do not move assets between groups without documenting build and patching impact.

## Loading Rules

- Track ownership of Addressables handles.
- Release handles according to the same layer that loaded them.
- Avoid synchronous loading in gameplay paths.
- Handle load failure at real boundaries with actionable logs.
- Do not keep references to unloaded scene assets or released Addressables.

## Validation

- Run Addressables Analyze or project validation when available.
- For build-impacting changes, run an Addressables content build or explain why it was not run.
- Add tests around key resolution, catalog-facing config, or loader behavior when possible.

## Final Response Checklist

- Mention keys, labels, groups, or assets changed.
- Mention load/release ownership.
- Mention Addressables validation/build status.
````

## 代理需要维护的 Unity 文档

Unity 项目文档不应只描述代码，还要描述资源和编辑器约定。

推荐文档：

```plaintext
docs/
  architecture.md              # 模块、依赖方向、启动流程
  scenes-and-entrypoints.md     # 场景用途、加载顺序、入口脚本
  asset-pipeline.md             # Prefab、SO、Addressables、命名规范
  conventions.md                # C#、Unity 生命周期、Inspector 规则
  testing.md                    # EditMode、PlayMode、CI、覆盖范围
  build-and-release.md          # 平台、构建参数、版本号、签名
  performance.md                # GC、对象池、Update 预算、Profiler 流程
  cleanup.md                    # AI 垃圾回收的边界、提示词、PR 规则
```

`docs/scenes-and-entrypoints.md` 示例：

```markdown
# Scenes And Entry Points

## Boot.unity

Purpose: initializes project-wide services and loads the next scene.
Main scripts:
- `Project.Core.Bootstrap.GameBootstrapper`
- `Project.Core.SceneLoading.SceneLoader`

Rules:
- Do not place gameplay objects in Boot scene.
- Do not make Boot depend on UI or Gameplay assemblies.
- New global systems must be registered through the bootstrap flow, not via hidden scene searches.

## Gameplay.unity

Purpose: contains the playable game loop.
Main roots:
- `GameplayRoot`
- `PlayerSpawnRoot`
- `LevelRuntimeRoot`

Rules:
- Scene references should be wired in prefabs or root installers.
- Do not add duplicate manager GameObjects without checking existing roots.
```

`docs/asset-pipeline.md` 示例：

```markdown
# Asset Pipeline

## Prefabs

- Runtime prefabs live under `Assets/_Project/Prefabs`.
- UI prefabs live under `Assets/_Project/Prefabs/UI`.
- Do not unpack third-party prefabs in place.
- Do not rename serialized fields without migration notes.

## ScriptableObjects

- Balance configs live under `Assets/_Project/Configs/GameBalance`.
- ScriptableObject types live under `Project.Core.Config` or the owning feature namespace.
- Runtime systems may read config assets but must not mutate imported asset instances during play.

## Addressables

- Addressable keys must be stable.
- Do not hard-code Addressable keys in multiple places; centralize them in constants or config.
- Validate Addressables before release builds.
```

## Unity C# 编码规则：减少 AI Slop

Unity 项目的 AI slop 往往不是语法错误，而是“看起来能跑，但工程越来越烂”：

- 新增很多 `Manager`、`Controller`、`Handler`，职责重叠
- 到处 `FindObjectOfType` 和 `DontDestroyOnLoad`
- 改字段名导致 Prefab 引用丢失
- 在 `Update` 里分配 GC 或做昂贵查询
- 编辑器脚本混入 Runtime assembly
- 测试缺失，只靠手动点场景
- 留下旧 Prefab、旧 ScriptableObject、旧分支逻辑

可以在 `AGENTS.md` 里强制：

```markdown
## Minimal Changes / No Slop

- Re-read your diff before finishing. Delete unused code, stale branches, unused serialized fields, and abandoned helper methods.
- Do not add narration comments. Comments must explain non-obvious Unity constraints, lifecycle ordering, serialization migration, or platform-specific behavior.
- Do not create a new manager/service if an existing system owns the responsibility.
- Do not create a helper class for a single caller.
- Do not add speculative null checks for serialized fields everywhere. Validate required references in `OnValidate` or targeted startup validation.
- Do not use `FindObjectOfType`, `GameObject.Find`, or global singleton lookup as a first choice.
- Do not rename serialized fields without `[FormerlySerializedAs]` and a migration note.
- Do not move assets unless the task requires it.
- Do not edit generated files, package cache files, or third-party assets.
```

字段改名示例：

```csharp
using UnityEngine;
using UnityEngine.Serialization;

namespace Project.Gameplay.Player
{
    public sealed class PlayerMovement : MonoBehaviour
    {
        [FormerlySerializedAs("moveSpeed")]
        [SerializeField] private float movementSpeed = 5f;
    }
}
```

这条规则对 Unity 很重要。没有 `[FormerlySerializedAs]`，代理一次普通重命名就可能让所有 Prefab 上的数值回到默认值。

## 用 OnValidate 和编辑器验证建立护栏

Unity 项目里，很多错误不会被 C# 编译器发现：Prefab 少绑了引用、配置数值非法、Addressable key 不存在、场景没有必要入口对象。

可以用 `OnValidate` 做局部约束：

```csharp
using UnityEngine;

namespace Project.Gameplay.Weapons
{
    public sealed class WeaponConfig : ScriptableObject
    {
        [SerializeField] private float damage = 10f;
        [SerializeField] private float cooldownSeconds = 0.25f;

        public float Damage => damage;
        public float CooldownSeconds => cooldownSeconds;

        private void OnValidate()
        {
            damage = Mathf.Max(0f, damage);
            cooldownSeconds = Mathf.Max(0.01f, cooldownSeconds);
        }
    }
}
```

也可以写项目级验证菜单，给代理和 CI 调用：

```csharp
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;

namespace Project.Editor.Validation
{
    public static class ProjectValidator
    {
        [MenuItem("Project/Validation/Run All")]
        public static void RunAll()
        {
            ValidateWeaponConfigs();
            Debug.Log("Project validation passed.");
        }

        private static void ValidateWeaponConfigs()
        {
            string[] guids = AssetDatabase.FindAssets("t:WeaponConfig", new[] { "Assets/_Project/Configs" });

            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                var config = AssetDatabase.LoadAssetAtPath<ScriptableObject>(path);

                if (config == null)
                {
                    throw new BuildFailedException($"Invalid WeaponConfig asset at {path}");
                }
            }
        }
    }
}
#endif
```

更完整的项目可以把验证做成 `-executeMethod` 可调用的静态入口：

```csharp
#if UNITY_EDITOR
namespace Project.Editor.Validation
{
    public static class ProjectValidationCommand
    {
        public static void RunAll()
        {
            ProjectValidator.RunAll();
        }
    }
}
#endif
```

然后 CI 或本地脚本执行：

```bash
Unity \
  -batchmode \
  -quit \
  -projectPath . \
  -executeMethod Project.Editor.Validation.ProjectValidationCommand.RunAll \
  -logFile Logs/unity-validation.log
```

## 让糟糕代码难以提交

Unity 项目也应该使用提交前钩子。可以用 `pre-commit`、Husky、lefthook 或 Git hooks。

示例 `.pre-commit-config.yaml`：

```yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
      - id: check-yaml
      - id: check-json
      - id: end-of-file-fixer
      - id: trailing-whitespace
        exclude: ".*(.unity|.prefab|.asset|.meta)$"

  - repo: local
    hooks:
      - id: dotnet-format
        name: dotnet format
        entry: dotnet format ProjectName.sln --verify-no-changes
        language: system
        files: "\\.cs$"
        pass_filenames: false
```

这里要显式写 solution 路径，不要依赖 `dotnet format` 在仓库根目录自动猜测。Unity 项目如果忽略 `.sln` / `.csproj`，需要先打开 Unity 或用 Unity 批处理生成 C# project files，再运行：

```bash
dotnet format ProjectName.sln --verify-no-changes
```

如果团队使用 Rider/ReSharper，也可以在 CI 中加入 InspectCode：

```bash
jb inspectcode ProjectName.sln --output=inspectcode.xml
```

不要指望代理每次都记得格式化、跑测试。把这些变成钩子和 CI，而不是口头约定。

## 一个命令验证所有内容

代理需要一个明确终点线。Unity 项目推荐准备 `tools/validate-unity.sh` 或 `tools/validate-unity.ps1`。

示例 `tools/validate-unity.sh`：

```bash
#!/usr/bin/env bash
set -euo pipefail

UNITY_PATH="${UNITY_PATH:-Unity}"
PROJECT_PATH="$(pwd)"
LOG_DIR="$PROJECT_PATH/Logs"
mkdir -p "$LOG_DIR"

"$UNITY_PATH" \
  -batchmode \
  -quit \
  -projectPath "$PROJECT_PATH" \
  -runTests \
  -testPlatform EditMode \
  -testResults "$LOG_DIR/editmode-results.xml" \
  -logFile "$LOG_DIR/editmode.log"

"$UNITY_PATH" \
  -batchmode \
  -quit \
  -projectPath "$PROJECT_PATH" \
  -runTests \
  -testPlatform PlayMode \
  -testResults "$LOG_DIR/playmode-results.xml" \
  -logFile "$LOG_DIR/playmode.log"

"$UNITY_PATH" \
  -batchmode \
  -quit \
  -projectPath "$PROJECT_PATH" \
  -executeMethod Project.Editor.Validation.ProjectValidationCommand.RunAll \
  -logFile "$LOG_DIR/project-validation.log"
```

然后在 `AGENTS.md` 中写清楚：

````markdown
Before considering a task complete, run:

```bash
./tools/validate-unity.sh
```

If it fails, fix the errors rather than working around checks.
Do not delete tests, weaken assertions, or bypass Unity validation unless explicitly asked.
````

Windows 团队可以提供 PowerShell 版本：

```powershell
$ErrorActionPreference = "Stop"

$UnityPath = if ($env:UNITY_PATH) { $env:UNITY_PATH } else { "Unity.exe" }
$ProjectPath = Get-Location
$LogDir = Join-Path $ProjectPath "Logs"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null

& $UnityPath -batchmode -quit -projectPath $ProjectPath -runTests -testPlatform EditMode -testResults "$LogDir/editmode-results.xml" -logFile "$LogDir/editmode.log"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

& $UnityPath -batchmode -quit -projectPath $ProjectPath -runTests -testPlatform PlayMode -testResults "$LogDir/playmode-results.xml" -logFile "$LogDir/playmode.log"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

& $UnityPath -batchmode -quit -projectPath $ProjectPath -executeMethod Project.Editor.Validation.ProjectValidationCommand.RunAll -logFile "$LogDir/project-validation.log"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
```

## 始终使用测试驱动开发

Unity 的 TDD 可以分成三层：

1. **纯 C# 单元测试**：不依赖 Unity 场景，测试规则、计算、状态机、存档格式。
2. **EditMode 测试**：测试 ScriptableObject、编辑器验证、资源导入规则、Prefab 结构。
3. **PlayMode 测试**：测试场景加载、MonoBehaviour 生命周期、输入、UI、玩法流程。

代理最适合先写测试规格，再写实现。

例如，先让代理生成测试：

```csharp
using NUnit.Framework;
using Project.Gameplay.Combat;

namespace Project.Tests.EditMode.Gameplay.Combat
{
    public sealed class DamageCalculatorTests
    {
        [Test]
        public void CalculateDamage_DoesNotReturnNegativeDamage()
        {
            int damage = DamageCalculator.CalculateDamage(baseDamage: 5, armor: 999);

            Assert.That(damage, Is.EqualTo(0));
        }

        [Test]
        public void CalculateDamage_AppliesCriticalMultiplierAfterArmorReduction()
        {
            int damage = DamageCalculator.CalculateDamage(baseDamage: 20, armor: 5, criticalMultiplier: 2f);

            Assert.That(damage, Is.EqualTo(30));
        }
    }
}
```

人工先检查测试是否符合需求。确认后，再让代理实现：

```csharp
namespace Project.Gameplay.Combat
{
    public static class DamageCalculator
    {
        public static int CalculateDamage(int baseDamage, int armor, float criticalMultiplier = 1f)
        {
            int reducedDamage = System.Math.Max(0, baseDamage - armor);
            return (int)(reducedDamage * criticalMultiplier);
        }
    }
}
```

好测试不仅是质量保障，也是给代理的监督信号。没有测试时，代理会倾向于“看起来合理”；有测试时，代理会被迫对齐明确行为。

## Unity CI：本地护栏不够时

本地 hooks 只能拦住一部分问题。Unity 项目最好在 CI 中运行：

- C# 编译
- EditMode 测试
- PlayMode 测试
- 项目自定义验证
- Addressables 构建或分析
- 目标平台构建
- 静态分析
- Secret 扫描
- 许可证和第三方依赖审计

GitHub Actions 示例：

```yaml
name: Unity Validate

on:
  pull_request:
  workflow_dispatch:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          lfs: true

      - uses: actions/cache@v4
        with:
          path: Library
          key: Library-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }}
          restore-keys: |
            Library-

      - name: Run EditMode tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
        with:
          testMode: EditMode
          artifactsPath: test-results/editmode

      - name: Run PlayMode tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
        with:
          testMode: PlayMode
          artifactsPath: test-results/playmode

      - name: Run project validation
        uses: game-ci/unity-builder@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
        with:
          targetPlatform: StandaloneWindows64
          buildMethod: Project.Editor.Validation.ProjectValidationCommand.RunAll

      - name: Build player
        uses: game-ci/unity-builder@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
        with:
          targetPlatform: StandaloneWindows64
```

对于大型项目，还可以加入：

- Addressables Analyze
- AssetBundle 构建验证
- 平台特定 smoke test
- IL2CPP 构建
- Android/iOS 签名检查
- 内存和包体积预算检查

## Unity 版“垃圾回收”：定期清理 AI Slop

即使有规则，AI slop 仍然会出现。Unity 项目可以定期让代理做小范围维护 PR，但必须限制权限和范围。

适合自动清理的事项：

- 删除无引用的私有方法和类
- 清理未使用 using
- 同步 `AGENTS.md` 和 `docs/`
- 查找重复 Manager/Service
- 查找 Editor 代码误入 Runtime assembly
- 查找空目录、过期测试、无效文档引用
- 查找没有 `[FormerlySerializedAs]` 的可疑字段重命名

不适合自动清理的事项：

- 大规模移动资产
- 批量重命名 Prefab、场景、ScriptableObject
- 自动改 Project Settings
- 自动升级 Unity 版本或包版本
- 自动重写核心架构

垃圾回收提示词示例：

```markdown
Read `AGENTS.md` and `docs/cleanup.md`.
Make one small, safe maintenance improvement only.
Prefer C# cleanup over asset moves.
Do not rename serialized fields.
Do not move `.unity`, `.prefab`, `.asset`, or `.meta` files.
Do not modify third-party assets.
If no safe cleanup exists, leave the repository unchanged.
Before finishing, run `./tools/validate-unity.sh` if Unity is available.
```

## Unity 项目的安全与供应链

Unity 项目同样有安全风险，尤其是：

- 第三方插件引入恶意代码
- API key 写入 ScriptableObject、场景或 `Resources`
- 移动端客户端包含不该存在的服务端密钥
- Asset Store 插件包含过宽权限
- Addressables 或远程配置被滥用
- 内购、经济系统、存档校验逻辑只在客户端实现

建议：

- 使用 secret scanning 检查 `.cs`、`.asset`、`.prefab`、`.unity`、`.json`。
- 不把服务端密钥放进 Unity 客户端。
- 对内购、货币、排行榜、账号权限做服务端校验。
- 审查第三方插件更新。
- CI 中加入依赖和许可证审计。

## 始终思考 Unity 工程给代理提供了什么

编码代理的输出，强烈依赖仓库环境给它提供的约束。

如果 Unity 项目只有一个巨大的 `Assets/`、没有 asmdef、没有测试、没有文档、没有验证脚本，代理就会倾向于生成“能编译但脏”的代码。

如果项目提供：

- 清晰目录结构
- 明确 asmdef 边界
- 可执行测试
- 项目级验证命令
- 严格 AGENTS.md
- 资源和场景文档
- 提交钩子和 CI

那么代理就更容易写出可维护的 Unity C# 代码。

关键不是让 AI “更听话”，而是让工程环境本身变得更难写坏。

## 附录 B：完整项目文档模板

下面是上文出现的 `AGENTS.md` 和 `docs/*.md` 可直接落地版本。它们的目标不是替代真实项目文档，而是给编码代理一个稳定的起点。落地时要把占位符替换成真实项目名称、Unity 版本、场景、程序集和平台。

### `AGENTS.md`

````markdown
# Project Unity Coding Rules

## Overview

This is a Unity project built with Unity 2022.3 LTS.
Runtime code lives in `Assets/_Project/Scripts/Runtime`.
Editor tools live in `Assets/_Project/Scripts/Editor`.
Project assets live under `Assets/_Project`.
Third-party assets live under `Assets/ThirdParty` or `Assets/Plugins`.

## Read Before Editing

- `docs/architecture.md`
- `docs/conventions.md`
- `docs/scenes-and-entrypoints.md`
- `docs/asset-pipeline.md`
- `docs/testing.md`
- Relevant `.agents/skills/*/SKILL.md` files for the task

## Entry Points

- Boot scene: `Assets/_Project/Scenes/Boot.unity`
- Main menu scene: `Assets/_Project/Scenes/MainMenu.unity`
- Gameplay scene: `Assets/_Project/Scenes/Gameplay.unity`
- Game bootstrap: `Project.Core.Bootstrap.GameBootstrapper`

## Mandatory Rules

- Do not create scripts in `Assets/` root.
- Do not put project code in global namespace.
- Do not edit `.meta` files manually unless the task explicitly requires asset GUID work.
- Do not move or rename assets casually; Unity references depend on GUIDs.
- Do not rename serialized fields without `[FormerlySerializedAs]` and a migration note.
- Do not modify `ProjectSettings/` unless the task is about build settings, input, quality, graphics, packages, or player settings.
- Do not modify third-party plugin code; wrap it from project code instead.
- Prefer editing existing components over adding duplicate manager classes.
- Before adding a singleton, search for existing services, installers, bootstrap code, and ScriptableObject configs.

## C# Style

- Use explicit namespaces matching assembly/module names.
- Use `private` fields with `[SerializeField]` for inspector references.
- Avoid public mutable fields.
- Avoid `FindObjectOfType`, `GameObject.Find`, and tag-based lookup in gameplay code unless there is no stable reference path.
- Avoid `async void` except Unity event handlers where unavoidable.
- Prefer cancellation-aware async flows when using UniTask or Tasks.
- Do not catch and rethrow exceptions without adding useful context.
- Do not add comments that narrate obvious code.

## Unity Lifecycle Rules

- Keep `Awake` for local initialization.
- Keep `Start` for cross-object initialization that depends on scene setup.
- Keep `Update`, `LateUpdate`, and `FixedUpdate` small and allocation-free.
- Unsubscribe events in `OnDisable` or `OnDestroy` consistently with where they were subscribed.
- Do not mutate imported ScriptableObject assets as runtime state.

## Asset Rules

- `.meta` files must be committed.
- Unity serialization must use Force Text.
- Version Control mode must use Visible Meta Files.
- Do not unpack, restructure, or rename prefabs unless the task explicitly requires it.
- Do not modify scenes unless the requested behavior requires scene wiring.
- Mention prefab, scene, ScriptableObject, Addressables, or asmdef impact in the final response.

## Minimal Changes / No Slop

- Re-read your diff before finishing and remove unused code, stale branches, unused serialized fields, and abandoned helpers.
- Do not add single-use abstractions.
- Do not add speculative null checks everywhere; validate at boundaries and targeted validation points.
- Do not leave commented-out code or tombstone comments.
- Do not perform broad cleanup around an unrelated bug fix.

## Validation

Before considering a task complete, run:

```bash
./tools/validate-unity.sh
```

If validation fails, fix the cause. Do not weaken tests, remove analyzers, delete assertions, or bypass compilation unless explicitly asked.

If Unity is unavailable, state that validation was not run and list the exact command the user should run.
````

### `docs/architecture.md`

````markdown
# Architecture

## Purpose

This document describes the stable module boundaries, dependency direction, and runtime ownership model for the Unity project. Coding agents must read this before changing cross-module behavior.

## Project Layout

```plaintext
Assets/_Project/
  Configs/
  Prefabs/
  Scenes/
  Scripts/
    Runtime/
      Core/
      Gameplay/
      UI/
      Infrastructure/
    Editor/
    Tests/
      EditMode/
      PlayMode/
```

## Assemblies

| Assembly | Path | Responsibility | May Reference |
| --- | --- | --- | --- |
| `Project.Core` | `Assets/_Project/Scripts/Runtime/Core` | Shared runtime primitives, bootstrap contracts, scene loading interfaces | Unity runtime packages only |
| `Project.Gameplay` | `Assets/_Project/Scripts/Runtime/Gameplay` | Gameplay rules, player, enemies, combat, level systems | `Project.Core` |
| `Project.UI` | `Assets/_Project/Scripts/Runtime/UI` | UI screens, widgets, view controllers | `Project.Core` |
| `Project.Infrastructure` | `Assets/_Project/Scripts/Runtime/Infrastructure` | Save, platform, analytics, remote config, adapters | `Project.Core` |
| `Project.Editor` | `Assets/_Project/Scripts/Editor` | Editor tools, validators, build scripts | Runtime assemblies as needed |
| `Project.Tests.EditMode` | `Assets/_Project/Scripts/Tests/EditMode` | EditMode tests | Runtime and editor assemblies as needed |
| `Project.Tests.PlayMode` | `Assets/_Project/Scripts/Tests/PlayMode` | PlayMode tests | Runtime assemblies |

## Dependency Rules

- `Core` must not reference `Gameplay`, `UI`, or `Infrastructure`.
- `Gameplay` must not call UI directly; communicate through events, state, or application services.
- `UI` must not implement gameplay, save, payment, or network business logic.
- Runtime assemblies must not reference `UnityEditor`.
- Editor assemblies may reference runtime assemblies, but runtime assemblies may not reference editor assemblies.
- New modules require an `.asmdef` and an entry in this document.

## Runtime Ownership

- Bootstrapping starts in `Project.Core.Bootstrap.GameBootstrapper` from `Boot.unity`.
- Persistent services are created by the bootstrap flow, not by hidden scene search.
- Scene-specific objects are owned by scene roots and must be released on scene unload.
- Imported ScriptableObject assets are configuration, not mutable runtime state.
- Runtime state that derives from ScriptableObjects must be copied into plain C# objects or scene-owned components.

## Scene Loading

- `Boot.unity` initializes global services and loads the next scene.
- `MainMenu.unity` owns menu UI and user entry flow.
- `Gameplay.unity` owns gameplay scene roots and gameplay-only objects.
- Additive scenes must document ownership, loading trigger, and unload trigger in `docs/scenes-and-entrypoints.md`.

## Adding A Feature

1. Identify the owning assembly.
2. Search for existing services, roots, prefabs, configs, and tests.
3. Add the smallest code change in the owning module.
4. Add or update tests.
5. Update docs if scenes, public contracts, assets, or assembly boundaries change.
6. Run `./tools/validate-unity.sh`.
````

### `docs/conventions.md`

````markdown
# Conventions

## C# Naming

- Namespaces start with `Project` and follow the owning module, for example `Project.Gameplay.Combat`.
- MonoBehaviour class names describe behavior, not vague roles like `Manager` unless the existing architecture already owns that concept.
- Serialized private fields use camelCase.
- Public properties use PascalCase and expose read-only state unless mutation is intentional.
- Async methods end with `Async` unless they are Unity event handlers.

## File And Folder Rules

- One top-level public type per `.cs` file unless types are tightly coupled small value types.
- Runtime code goes under `Assets/_Project/Scripts/Runtime`.
- Editor code goes under `Assets/_Project/Scripts/Editor` or an Editor-only asmdef.
- Tests go under `Assets/_Project/Scripts/Tests/EditMode` or `Assets/_Project/Scripts/Tests/PlayMode`.
- Do not place project scripts directly under `Assets/`.

## Serialized Fields

- Prefer `[SerializeField] private` over public fields.
- Preserve serialized field names.
- If a serialized field is renamed, add `[FormerlySerializedAs("oldName")]`.
- Do not remove serialized fields without checking prefabs and scenes that may use them.
- Required scene or prefab references should be validated in `OnValidate` or project validation.

## Unity Lifecycle

- `Awake`: initialize local state and cache local components.
- `OnEnable`: subscribe to events or start object-scoped work.
- `Start`: perform initialization that depends on other scene objects being awake.
- `Update`: keep small and allocation-free.
- `OnDisable`: unsubscribe from events or cancel object-scoped work.
- `OnDestroy`: release resources not already handled by disable flow.

## Comments

- Do not write comments that restate code.
- Do write comments for hidden Unity constraints, serialization migration, platform-specific behavior, and surprising ordering requirements.
- Do not leave commented-out code.

## Error Handling

- Validate at true boundaries: user input, save data, network responses, external SDK callbacks, Addressables loads, and editor validation.
- Do not catch and rethrow without adding context.
- Use actionable logs that include asset paths, scene names, object names, or keys when relevant.

## Prohibited Defaults

- No new global singleton without checking existing bootstrap/service patterns.
- No `FindObjectOfType` or `GameObject.Find` as a first choice.
- No runtime dependency on `UnityEditor`.
- No broad asset moves during code-only tasks.
- No speculative architecture rewrites.
````

### `docs/scenes-and-entrypoints.md`

````markdown
# Scenes And Entry Points

## Scene List

| Scene | Path | Purpose | Owner |
| --- | --- | --- | --- |
| Boot | `Assets/_Project/Scenes/Boot.unity` | Initializes global services and loads the next scene | Core |
| MainMenu | `Assets/_Project/Scenes/MainMenu.unity` | Menu flow, profile selection, settings entry | UI |
| Gameplay | `Assets/_Project/Scenes/Gameplay.unity` | Main playable loop | Gameplay |

## Boot.unity

Purpose: initializes project-wide services and loads the next scene.

Main scripts:

- `Project.Core.Bootstrap.GameBootstrapper`
- `Project.Core.SceneLoading.SceneLoader`

Rules:

- Do not place gameplay objects in Boot scene.
- Do not make Boot depend on UI or Gameplay assemblies.
- New global systems must be registered through the bootstrap flow, not via hidden scene searches.
- Persistent objects must have clear ownership and teardown rules.

## MainMenu.unity

Purpose: contains menu UI and non-gameplay user flow.

Main roots:

- `MainMenuRoot`
- `MenuCanvas`
- `SettingsPanelRoot`

Rules:

- UI controllers delegate to services; they do not implement save, economy, or network logic.
- Button events must be backed by serialized references or explicit binding code.
- Preserve controller/keyboard navigation when changing menu UI.

## Gameplay.unity

Purpose: contains the playable game loop.

Main roots:

- `GameplayRoot`
- `PlayerSpawnRoot`
- `LevelRuntimeRoot`
- `GameplayCanvas`

Rules:

- Scene references should be wired in prefabs or root installers.
- Do not add duplicate manager GameObjects without checking existing roots.
- Gameplay scene objects must not assume MainMenu objects still exist.
- Scene-owned services must release subscriptions and Addressables handles on unload.

## Adding Or Changing Scenes

When adding or changing a scene:

1. Add the scene path and purpose to this document.
2. Document root GameObjects and entry scripts.
3. Update build settings or Addressables docs if loading changes.
4. Add PlayMode tests for critical loading behavior when practical.
5. Mention scene impact in the final response.
````

### `docs/asset-pipeline.md`

````markdown
# Asset Pipeline

## Unity Serialization

Project Settings must use:

```plaintext
Version Control Mode: Visible Meta Files
Asset Serialization Mode: Force Text
```

Rules:

- `.meta` files must be committed.
- Do not manually edit `.meta` files unless fixing GUID or merge issues.
- Do not move or rename assets casually; references depend on GUIDs and paths.
- Use Git LFS for large binary assets.
- Use UnityYAMLMerge for `.unity`, `.prefab`, `.asset`, `.controller`, `.anim`, and `.mat` files.

## Prefabs

- Runtime prefabs live under `Assets/_Project/Prefabs`.
- UI prefabs live under `Assets/_Project/Prefabs/UI`.
- Gameplay prefabs live under `Assets/_Project/Prefabs/Gameplay`.
- System prefabs live under `Assets/_Project/Prefabs/Systems`.
- Do not unpack third-party prefabs in place.
- Do not rename serialized fields without `[FormerlySerializedAs]` and migration notes.
- Prefer prefab variants when a variant is truly needed; do not create duplicate prefabs for small temporary differences.

## ScriptableObjects

- Balance configs live under `Assets/_Project/Configs/GameBalance`.
- ScriptableObject types live under `Project.Core.Config` or the owning feature namespace.
- Runtime systems may read config assets but must not mutate imported asset instances during play.
- If runtime mutation is needed, copy ScriptableObject data into runtime state.
- Required fields should be validated by `OnValidate` or project validation.

## Addressables

- Addressable keys must be stable.
- Do not hard-code the same key in multiple places; centralize keys in constants or config.
- Labels must have clear loading purpose.
- Do not move assets between groups without documenting bundle, patch, and remote content impact.
- Validate Addressables before release builds.

## Art And Audio

- Source art files such as `.psd` and `.blend` use Git LFS.
- Runtime textures, models, and audio should follow platform import presets.
- Do not change compression, max size, or platform overrides unless the task is about asset optimization or visual/audio quality.
- Document large asset additions in the final response.

## Generated Assets

- Do not edit generated assets manually.
- Generated file locations and regeneration commands must be documented near the generator or in `docs/build-and-release.md`.
- If generated assets change, mention the generator command that produced them.
````

### `docs/testing.md`

````markdown
# Testing

## Test Layers

| Layer | Location | Purpose |
| --- | --- | --- |
| Pure C# tests | `Assets/_Project/Scripts/Tests/EditMode` | Rules, calculators, state machines, save formats |
| EditMode tests | `Assets/_Project/Scripts/Tests/EditMode` | ScriptableObjects, editor validation, import rules, prefab structure |
| PlayMode tests | `Assets/_Project/Scripts/Tests/PlayMode` | Scene loading, MonoBehaviour lifecycle, UI, gameplay smoke tests |

## Commands

Run all local validation:

```bash
./tools/validate-unity.sh
```

Run EditMode tests only:

```bash
Unity -batchmode -quit -projectPath . -runTests -testPlatform EditMode -testResults Logs/editmode-results.xml -logFile Logs/editmode.log
```

Run PlayMode tests only:

```bash
Unity -batchmode -quit -projectPath . -runTests -testPlatform PlayMode -testResults Logs/playmode-results.xml -logFile Logs/playmode.log
```

Run project validation:

```bash
Unity -batchmode -quit -projectPath . -executeMethod Project.Editor.Validation.ProjectValidationCommand.RunAll -logFile Logs/project-validation.log
```

## Testing Rules For Agents

- Write or update tests before implementation when behavior is non-trivial.
- Human review should confirm generated tests describe the intended behavior before implementation begins.
- Do not delete tests to make validation pass.
- Do not weaken assertions unless the requirement changed.
- Prefer pure C# tests for deterministic logic.
- Use PlayMode tests for lifecycle, scene, input, and UI behavior that cannot be proven in EditMode.

## What To Test

- Calculators, state machines, cooldowns, timers, and progression rules.
- Save/load serialization and migration.
- ScriptableObject validation and default constraints.
- Addressables key resolution and loader ownership.
- Scene boot and critical smoke flows.
- UI presenter formatting and critical button flows.

## What Not To Over-Test

- Unity engine internals.
- Trivial property pass-through.
- Visual polish that needs human review unless screenshot tooling exists.
- Performance claims without profiler or benchmark support.

## CI Expectations

Pull requests should run:

- EditMode tests
- PlayMode tests for critical flows
- Project validation command
- Build for at least one representative target platform

If a check cannot run locally, the final response must say so and name the CI check that should cover it.
````

### `docs/build-and-release.md`

````markdown
# Build And Release

## Unity Version

Unity version: `2022.3.x LTS`

The Unity version must be pinned in `ProjectSettings/ProjectVersion.txt`. Do not upgrade Unity versions unless explicitly asked.

## Supported Targets

| Platform | Target | Notes |
| --- | --- | --- |
| Windows | `StandaloneWindows64` | Default CI build target |
| macOS | `StandaloneOSX` | Add if release requires it |
| Android | `Android` | Requires keystore and signing setup |
| iOS | `iOS` | Requires Xcode signing pipeline |

## Local Build Command

```bash
Unity -batchmode -quit -projectPath . -executeMethod Project.Editor.Build.BuildCommand.BuildWindows -logFile Logs/build-windows.log
```

Replace the build method with the real project build entry point.

## CI Build Requirements

- Checkout must include Git LFS assets.
- CI must use the pinned Unity version.
- CI must run tests and project validation before release builds.
- Build logs must be uploaded as artifacts on failure.
- Release builds must not contain development-only scenes or test assets.

## Versioning

- Update application version through the documented build pipeline, not by ad-hoc Project Settings edits.
- Keep bundle identifiers stable.
- Platform-specific version codes must be monotonic.
- Mention version or build setting changes in the final response.

## Addressables And Remote Content

- Validate Addressables before release.
- Document content update restrictions before moving assets between groups.
- Catalog and remote paths must match the target environment.
- Do not change remote load paths without release owner approval.

## Secrets And Signing

- Do not commit keystores, provisioning profiles, API keys, or service account files.
- Signing credentials must come from CI secrets or local secure storage.
- Unity clients must not contain server-only secrets.

## Release Checklist

- `./tools/validate-unity.sh` passes.
- Target platform build passes.
- Addressables validation/build passes if Addressables changed.
- Version and build number are correct.
- Scenes in build settings are correct.
- No development-only flags are enabled for production.
````

### `docs/performance.md`

````markdown
# Performance

## Budgets

Define real budgets per project and platform. Starting placeholders:

| Area | Budget |
| --- | --- |
| Frame time | 16.6 ms for 60 FPS target |
| GC allocations during gameplay | 0 B/frame in hot paths |
| Scene load | Project-specific |
| Memory | Platform-specific |
| Build size | Platform-specific |

## Hot Path Rules

- No per-frame LINQ in gameplay or UI hot paths.
- No repeated string formatting in `Update`, `LateUpdate`, `FixedUpdate`, or UI polling loops.
- Cache repeated component lookups.
- Avoid broad hierarchy searches during gameplay.
- Prefer event-driven UI updates over polling.
- Use pooling for frequently spawned short-lived objects.

## Profiling Workflow

1. Reproduce the performance issue in a stable scene or test flow.
2. Capture baseline profiler data.
3. Make the smallest targeted change.
4. Capture after-change data using the same scenario.
5. Document the measured result in the PR or final response.

## Memory Rules

- Release Addressables handles consistently.
- Do not keep scene object references in persistent services after scene unload.
- Avoid mutating imported ScriptableObject assets at runtime.
- Be cautious with large texture, audio, and animation imports.
- Use platform import overrides intentionally.

## UI Performance

- Avoid forcing layout rebuilds every frame.
- Avoid enabling/disabling large UI hierarchies repeatedly in hot flows.
- Prefer pooled list items for long or frequently refreshed lists.
- Do not leave invisible panels doing work.

## Physics Performance

- Use physics layers intentionally.
- Avoid unnecessary collision matrix expansion.
- Avoid expensive queries every frame without measuring.
- Keep `FixedUpdate` logic focused and deterministic.

## Agent Rules

- Do not claim performance improved without a measurement or clear mechanical reason.
- If profiling was not run, say so.
- Mention hot paths touched and expected allocation/frame-time impact.
````

### `docs/cleanup.md`

````markdown
# Cleanup Rules For AI Garbage Collection

## Purpose

This document defines safe maintenance work for periodic AI cleanup. The goal is to remove obvious slop without creating risky asset, scene, or architecture churn.

## Allowed Cleanup

Agents may make one small, focused cleanup PR for:

- Removing unused private methods, fields, or using directives.
- Removing dead code proven unreachable by current callers.
- Removing stale comments or commented-out code.
- Fixing documentation references to renamed or removed code.
- Updating factual sections of `AGENTS.md` and `docs/*.md` to match the current codebase.
- Moving editor-only code out of runtime assemblies when the fix is obvious and small.
- Adding missing validation around existing documented invariants.

## Disallowed Cleanup

Agents must not do these during automated cleanup unless explicitly asked:

- Move or rename `.unity`, `.prefab`, `.asset`, or `.meta` files.
- Rename serialized fields.
- Rewrite core architecture.
- Upgrade Unity, packages, or third-party plugins.
- Modify Project Settings broadly.
- Reorganize folders for aesthetics.
- Delete assets just because text search does not find references.
- Change public gameplay behavior without a test or explicit requirement.

## Required Process

1. Read `AGENTS.md` and this file.
2. Pick at most one small maintenance concern.
3. Search for references before deleting code.
4. Avoid asset moves and serialized field renames.
5. Run `./tools/validate-unity.sh` if Unity is available.
6. If no safe cleanup exists, leave the repository unchanged.

## Documentation Sync Scope

Agents may update factual sections only:

- Project structure
- Scene list
- Assembly list
- Entry points
- Test commands
- Build commands
- Asset locations
- Validation commands

Agents must not rewrite style, tone, architecture principles, or coding rules unless explicitly asked.

## Cleanup Prompt

```markdown
Read `AGENTS.md` and `docs/cleanup.md`.
Make one small, safe maintenance improvement only.
Prefer C# cleanup over asset moves.
Do not rename serialized fields.
Do not move `.unity`, `.prefab`, `.asset`, or `.meta` files.
Do not modify third-party assets.
If no safe cleanup exists, leave the repository unchanged.
Before finishing, run `./tools/validate-unity.sh` if Unity is available.
```

## Final Response Checklist

- State the single cleanup concern addressed.
- State files changed.
- State validation run status.
- State any skipped validation and why.
````
