Farmix 项目技术文档(Tech Doc)
0. 快速开始
场景与组件清单
- 打开
GameScene,确认这些对象存在且启用:Qix(挂载QixLite)、Level(挂载LevelManager)、Canvas、EventSystem、Main Camera。 QixLite会在运行时构建玩法网格和 UI;你不需要在层级里预先摆放网格格子。
- 打开
资源绑定(必需)
- 在
QixLite的 Inspector 中,拖拽绑定资源:地面 sprites、14 向边缘 mask、14 向轨迹(Trail)mask、Player/Sheep/Wolf/Bear/Locust/Pesticide 的静态 sprite 与动画帧数组;BGM 与 SFX;如果使用 TextMeshPro,也请绑定hudTMP。
- 在
关卡设置
- 在
Level(LevelManager)中编辑Levels列表以定义多个关卡。如果列表为空,会自动生成5 个默认关卡,难度逐级递增。
- 在
Build Settings
- 将
GameScene和MainMenu(或你使用的菜单场景名)加入 Build Settings。通关后,LevelManager会返回mainMenuSceneName。
- 将
1. 架构与职责
1.1 运行时对象与脚本边界
LevelManager(流程/难度)- 对外暴露
LevelConfig(生命数、单位数量、速度、计时器、计分、胜利占领比、蝗虫并发上限等)。 - 游戏开始:查找
QixLite并调用BeginLevel(cfg)注入关卡参数并启动关卡。 - 关卡结束:接收
QixLite的胜利回调,推进到下一关或返回主菜单。
- 对外暴露
QixLite(玩法/渲染/输入/视听)- 网格:用
GridLayoutGroup运行时构建width×height的Image网格,并维护状态机(Empty/Occupied/Trail)。 - 玩家移动:键盘 + 陀螺仪;进入/退出画线模式;闭合后进行填充、计分与胜负判定。
- 敌人与行为:Sheep(计分目标)、Wolf(多格占位移动)、Bear(边缘巡逻/计时提速/边缘规则)、Locust(并发刷新、啃食已占领区域、全局冷却)。
- UI/HUD:分数、生命、占领率、计时器(Text 或 TMP),以及动画/SFX 钩子。
- 特效/音频:序列帧动画、一次性尘土 FX、杀虫剂闪烁 FX、BGM/SFX 播放。
- 网格:用
1.2 “没有 LevelManager” 的兜底模式
- 如果场景里没有
LevelManager,QixLite.Start()会使用 Inspector 中的自身参数创建“Free Play”配置并自动开始。这个模式适合做单元测试/美术集成。
2. 网格、精灵与边缘规则(视觉 + 规则统一)
2.1 网格构建
- 运行时创建
Canvas、Grid、HUD、Actors等 Transform。Grid使用GridLayoutGroup;每个格子创建一个Image并初始化为空地 sprite。
2.2 格子状态
Cell:三态——Empty / Occupied / Trail。状态写入通过SetCell/SetCellDirect,并在写入后刷新邻居。
2.3 14 向边缘 Mask(Occupied / Trail 各一套)
- 位掩码:Up=1, Right=2, Down=4, Left=8。
Occupied与Trail各有 14 张组合边缘 sprite。ApplyCellSprite()会根据邻接关系选择正确 sprite。- 注意:无论是内部还是边界情况,为了让边缘高亮更直观,计算高亮时会把
Trail在视觉上当作空地来处理。
2.4 边界特例规则
- 边界上的
Occupied是否显示为“贴近空地的边界高亮”,通过采样仅内侧的 8 邻居来决定,避免高亮“扩散到场外”。 - 边界角落如果只有纯对角接触(cardinal mask = 0),规则上仍然可行走,但会渲染为纯实心占领(不高亮)以避免误导。
3. 玩家输入与移动状态机
3.1 输入优先级
- 键盘(WASD/方向键)优先;当两个轴都按下时,优先采用最后一次移动的轴。若无键盘输入,则读取陀螺仪(带 dead-zone/threshold)。
3.2 在 Occupied 上的可行走性
在
Occupied上行走需要格子是合法边缘:- 边界(Border):必须与
Empty(“空地”)存在 8 邻接接触。 - 内部(Interior):只有当存在 8 邻接接触
Empty时才合法;否则玩家被视为被困(trapped)。
- 边界(Border):必须与
踩到自己的
Trail(自撞)会立刻触发死亡处理。
3.3 画线与闭合
- 从占领区离开即进入画线模式;经过的格子变为
Trail并应用正确的 14 向轨迹 sprite。重新进入占领区会触发CloseAndFillArea()执行 flood fill 与结算。
3.4 自动救援(被困时)
如果玩家站在
Occupied上但不在合法边缘,会启动PlayerRescueAutopilot():- 先闪烁 1 秒(真实时间)→ 在
Occupied上 BFS 到最近的玩家可站立的占领边缘格 → 按当前玩家步速移动过去。
- 先闪烁 1 秒(真实时间)→ 在
4. 区域闭合、填充与计分
4.1 核心填充算法
- 从所有狼(它们的矩形占位)和熊出发 BFS,标记“可达的 Empty”。
- 未标记的
Empty判定为被封闭 → 设为Occupied;同时将整条Trail转为Occupied。 - 统计
filled格子数并加分:filled × scorePerCell;统计被封闭的羊并为每只加scorePerSheep。 - 被封闭在内部的熊会获得一条“回到最近合法边缘”的路径(仅在
Occupied上的直线路径)。 - 若
filled > 0,sealsCount自增(用于蝗虫刷新前置条件;见 §6)。 - 刷新边缘 sprite 与 UI。若占领率 ≥
winOccupyRatio,触发胜利。
BFS 与直线路径构造位于
FindPathToNearestEdge()/BuildStraightPath(),并保证每一步都在Occupied上。
5. 敌人系统
5.1 Sheep(羊)
- 随机生成在空地单格上;当被完整封闭时加分并播放计分 SFX。
5.2 Wolves(狼:矩形占位)
wolfSize为边长(默认 2 → 2×2 区域)。在空地矩形上生成;支持四方向动画(未配置时回退到通用动画)。- 轨迹切割可能触发“狼分离”检测(
CheckWolfSeparationByTrail();即便这里未展示片段也已预留接线)。
5.3 Bears(熊:边缘巡逻 / 计时提速 / 边缘规则)
- 初始在右上附近生成到最近
Occupied;若无效,则在Occupied上 BFS 找最近合法边缘作为出生点。 - 熊的可行走性与玩家一致:必须为合法边缘(边界/内部都要求与 Empty 存在 8 邻接接触)。
- 在计时器事件中速度可提升(
bearTilesPerSecondFast/Faster);HandleTimerTimeout()也可按关卡配置追加生成熊。
6. 蝗虫系统(并发、啃食、冷却)
6.1 刷新条件与并发上限
全局 tick 达到
locustSpawnInterval才尝试刷新;需要满足:- 至少 两次闭合(
sealsCount ≥ 2); - 当前时间 ≥
locustGlobalNoSpawnUntil(即不在全局冷却期); - 当前蝗虫数量
< maxLocusts; - 每次尝试有 50% 概率;
- 优先选择与空地接触的占领格(内部边缘)或内部占领边缘;若不存在则回退到任意占领格;
- 出生格不能与除羊以外的实体碰撞(玩家与羊不阻挡)。
- 至少 两次闭合(
maxLocusts来自关卡配置LevelConfig.locustMaxConcurrent,进入关卡时应用。
6.2 移动与旋转
- 每一步,蝗虫都会 BFS 到最近的**可吃的
Occupied**(非边界)。移动始终保持在Occupied上。步进方向会驱动 sprite 的旋转。 - 边界不可吃。如果只剩 一条合法占领边缘,蝗虫会自毁并启动全局冷却,避免把最后的边缘断开导致无解。
6.3 移除/死亡与特效
- 当新填充的区域与蝗虫所在的占领连通块连到一起时,蝗虫被击杀并播放杀虫剂闪烁 FX(默认 2 秒;
pesticideAnim或pesticideBaseSprite);随后启动全局冷却(locustRespawnCooldown)。 - 若只剩一条合法边缘或找不到可吃目标,蝗虫会消失(despawn)并进入冷却。
- 提供 spawn/death 的独立 SFX 钩子(
sfxLocustSpawn/sfxLocustEaten)。
7. 计时器与阶段事件
关卡计时
levelTimerSeconds每帧递减;当 ≤ 0 时触发HandleTimerTimeout(),随后计时器会重置为初始值。典型阶段动作(由关卡配置决定):
- 第一次超时:可选地通过
extraBearsOnFirstTimeout增加熊; - 提速:将熊速度切换到
bearTilesPerSecondFast/Faster。
- 第一次超时:可选地通过
计时器由 HUD/TMP 显示(
TimerText;使用hudTMP可构建更丰富的 HUD)。
8. UI / HUD / 字体
8.1 运行时构建 UI
ConstructIfNeeded()创建Canvas、Grid、HUD、Actors。HUD 默认包含TimerText;hudText作为扩展钩子(推荐 TMP)。
8.2 字体兼容性(Unity 6)
CreateText()使用builtinFont ? builtinFont : Resources.GetBuiltinResource<Font>("Arial.ttf")。Unity 6 内置 Arial 资源的名称/路径发生变化(常见报错:“Arial.ttf is no longer a valid built in font. Please use LegacyRuntime.ttf”)。
建议:
- 给
builtinFont指定工程内字体(最好与 TMP 同字体族),或 - 将 fallback 资源改为
"LegacyRuntime.ttf",或 - 将 HUD 全面迁移到 TextMeshPro。项目已经提供
hudTMP字段。
- 给
9. 音频系统
- 使用两个
AudioSource:musicSource播放 BGM(支持“升级版 BGM”),sfxSource播放短音效(脚步、计分、蝗虫刷新/消失、胜负等)。 - 工具方法:
PlayBGM(clip, loop)与PlaySfx(clip, vol)。 - 建议:使用
AudioMixer将 BGM/SFX 分组并加 limiter;叠加时尽量把 SFX 峰值控制在 -6 dBFS 以下,避免削波失真。
10. LevelConfig → 运行时映射
| LevelConfig 字段 | 用途 / 应用位置 |
|---|---|
lives |
进入关卡时若 resetLives 为 true,则覆盖 QixLite.lives |
numSheep / numWolves / wolfSize |
进入关卡时应用;用于 SpawnSheep/SpawnWolves |
initialBears / extraBearsOnFirstTimeout |
初始熊数量 + 第一次超时追加熊 |
playerStepPerSecond |
玩家步速(tiles/sec) |
wolfSpeed |
狼速度 → wolfTilesPerSecond |
bearSpeed / bearFastSpeed / bearFasterSpeed |
熊的三段速度 |
locustSpeed / SpawnInterval / RespawnCooldown |
蝗虫速度 / 刷新间隔 / 全局冷却 |
locustMaxConcurrent |
并发上限 → maxLocusts = Max(1, cfg.locustMaxConcurrent) |
winOccupyRatio |
胜利阈值(0.5–0.95) |
levelTimerSeconds |
初始计时值 |
scorePerCell / scorePerSheep |
填充每格得分 / 捕获羊得分 |
若
LevelManager.levels为空,Awake()会生成 5 个默认关卡,敌人逐渐加速、计时略微缩短。
11. 资源规范与美术说明
Sprites:
- 地面:
groundEmpty / groundOccupied / groundTrail / groundCrops。 - 边缘 mask:
Occupied14 张,Trail14 张(U/D/L/R、UR/UL/DR/DL、URD/ULD/DRL/URL、RL/UD)。命名清晰、像素尺寸一致。
- 地面:
动画序列帧:数组顺序即播放顺序;每个资源可配置 FPS。支持玩家/敌人/尘土/杀虫剂。
视觉缩放:每个 actor 有一个
xxxVisualScale,只影响视觉大小(不改变碰撞/规则)。
12. 性能与内存
- 网格大小:默认 48×27 ≈ 1296 个
Image。中高端设备可接受。避免重复重建网格;当前实现只构建一次,后续只替换 sprite。 - Actor:Sheep/Wolf/Bear/Locust/FX 按需 Instantiate/Destroy。若并发较高,建议引入对象池。
- 寻路/BFS:网格上是 O(w·h)。蝗虫频繁 BFS 时可限制搜索半径或加入局部缓存。
- 音频:对每步脚步音效做节流,或复用
AudioSource,避免同一帧多次播放。
13. QA 测试清单
功能
- 闭合后:空地填充正确;14 向边缘组合正确;整条
Trail变为Occupied。 - 捕获羊加分并播放 SFX。
- 熊出生点合法;巡逻始终走边缘;计时提速按配置触发。
- 狼 2×2 碰撞与分离逻辑正确。
- 蝗虫刷新满足
sealsCount/冷却/并发;不吃边界;只剩一条合法边缘时自毁。 - 自动救援:1 秒闪烁 + BFS 路径正确;地图在救援途中变化时不死锁。
- 计时器超时事件(第一次加熊/提速)与计时器重置正确。
- 胜利后
LevelManager.OnLevelWinFinished()能正确推进/回菜单。
兼容性
- HUD 使用 TMP 且指定字体;若仍用
Text,需设置builtinFont或 fallback 到LegacyRuntime.ttf。 - 移动端:陀螺仪阈值/dead-zone 手感合理;横竖屏 UI 安全区正确。
健壮性
-
LevelConfig极端值(0/负数)被 clamp(例如maxLocusts = Max(1, …))。 - 关卡切换时清理旧的 Actors 与 FX。
- 在暂停状态(死亡/救援/杀虫剂/狼清理)中,
Update要 early-out,避免竞态。
14. FAQ
HUD 字体报错(Unity 6)
- 现象:
Arial.ttf is no longer a valid built in font。 - 解决:给
builtinFont指定工程字体或把 fallback 改为LegacyRuntime.ttf;最好切换到 TMP。
- 现象:
HUD/计时器不显示
ConstructIfNeeded()会在 HUD 下创建TimerText。若 UI 被挡住,检查 sibling 顺序:gridRoot(0)<actorsRoot(1)<uiRoot(2)。
蝗虫“啃掉最后一条边缘”导致死局
- 已有防护:边界不可吃;当只剩一条合法内部边缘时蝗虫会自毁并进入冷却。
玩家在边界/角落“卡住”
- 合法边缘要求与 Empty 8 邻接接触;纯对角接触会渲染为实心占领(仍可走)。被困时会触发自动救援。
15. 扩展与可改造点
- 新增单位:沿用
Actor.Kind与SpawnXxx/MoveXxx模式,为新类型添加 sprite、动画与移动规则。 - 更高级 AI:给狼增加 flocking/避 Trail;给熊增加“追最近合法玩家边缘”(复用
FindPathToNearestEdge)。 - 脚本化关卡:将
LevelConfig序列化为 JSON/ScriptableObject 做关卡编辑器;在LevelManager.Awake中加载。 - 对象池:统一 Actors 与 FX 生命周期,降低 GC 与卡顿。
- 调试面板:在
QixLite增加 Debug 区(路径覆盖、mask bit、合法/非法边缘上色等)。
16. 团队协作习惯
- 命名:对 sprites/动画使用一致前缀(
occ_/tr_/wolf_up_XX等),方便批量绑定与搜索。 - 提交前自检:从开始跑到通关一局;检查边缘高亮、计分与音频;用 Deep Profile 检查分配。
- PR 说明:若改动关键路径(如
ApplyCellSprite / CloseAndFillArea / HandleLocust),请提供前后对比截图与性能数据。
17. 关键 API/方法(按用途)
- 关卡:
BeginLevel(cfg, levelIndex, resetLives)(进入),OnLevelWinFinished(caller)(推进) - 网格/边缘:
ApplyCellSprite / UpdateAllEdgeVisuals / BorderHasEmpty8 / HasEmptyNeighbor8 - 玩家:
ReadPlayerDirectionCardinal / StepPlayer / IsPlayerTrapped / PlayerRescueAutopilot - 闭合:
CloseAndFillArea / FindPathToNearestEdge / BuildStraightPath - 蝗虫:
HandleLocust / TrySpawnLocustPreferOccupied / IsEdibleOccupied / LocustNextStepToNearestEdible / KillLocustWithSmoke - 熊:
IsBearEdgeCell / FindFreeEdgeSpawnNear - UI:
ConstructIfNeeded / CreateText / UpdateHUD(HUD 更新在Update/结算逻辑中触发)
18. 版本与环境
- Unity:Unity 6(按截图),DX11;注意内置 Text 字体资源变更。
- 平台:支持键鼠 + 陀螺仪(移动端);iOS/Android 可补充触控输入映射与响应式 UI。
- 依赖:TextMeshPro(推荐用于所有 HUD 文本)。
附录:上手/运营清单
- 美术接线:把 14 向 masks 与动画序列帧拖到
QixLite中对应数组(注意顺序)。 - SFX 调参:在安静环境跑一局,确认脚步音效不疲劳;必要时加小的播放节流间隔。
- 关卡调参:从
Level 1起步:wolfSpeed 6, bearSpeed 4, win 0.75, timer 37s, maxLocusts 1;后续逐步提高速度/并发并缩短计时器。