这是一个“规则复杂、状态多、调参多”的玩法项目,我负责把它做成可迭代、可维护、可跨平台发布的工程。

Farmix 是一款 Qix-like 的领地占领玩法原型(农场主题):玩家在安全边界上移动,离开安全区就会在网格上“画线”,当轨迹闭合时触发 封闭区域判定 + 填充占领 + 计分。敌人系统包含 Sheep / Wolves / Bears / Locusts 等不同规则的单位,并加入了“蝗虫啃食占领地 + 杀虫剂冷却”的动态对抗机制。项目最终完成 可玩 Demo + 多关卡配置 + Android APK


关键词

  • 规则优先的网格架构:Empty / Occupied / Trail 三态数据,渲染用 14-direction mask 派生(视觉与规则解耦)
  • 闭合判定 + Flood Fill/BFS:以敌人可达性为核心的区域填充与计分
  • 模块化敌人 AI
    • Wolves:可调 2×2 等矩形占位移动
    • Bears:合法边界巡逻 + 计时阶段加速 + 受地形变化影响的自恢复
    • Locusts:并发上限、BFS 找可吃的 Occupied、全局冷却与自毁规则
  • 数据驱动难度与调参LevelManager.LevelConfig 暴露数量/速度/计分/计时/胜利阈值/蝗虫并发等参数
  • 跨平台体验:键盘 + 陀螺仪输入、分辨率/色彩适配、Android APK
  • 完整游戏流:主菜单 → 关卡流程 → 死亡/胜利反馈 → 结算弹窗 → 音频系统(BGM/SFX)

我的职责与工程贡献

我主要负责 工程架构 + 核心玩法实现 + 优化与联调

1) 网格数据与渲染解耦(规则先行)

  • 网格只存三态:Empty / Occupied / Trail
  • 渲染层不写死拼贴,而是通过 14 向边缘 mask 从邻接关系计算出正确的边缘/轨迹贴图
  • 这让系统能稳定迭代,例如:
    • “Trail 在视觉上当作空地参与边缘高亮,但在规则上仍然可致死/阻挡”
    • “边界合法性只检查内侧邻居(防止边框外的假邻接干扰)”

对应实现集中在:QixLite.cs(格子构建、状态机、边缘 mask 选择、视觉刷新)


2) 画线闭合、区域填充与计分(BFS/Flood Fill)

闭合后核心流程(工程上尽量保证可解释、可调参、可恢复):

  1. 从所有敌人(狼的矩形占位、熊等)出发 BFS,标记“可达的 Empty”
  2. 不可达的 Empty 判为“被封闭” → 转为 Occupied;同时把整条 Trail 转为 Occupied
  3. 增加得分:filledCells × scorePerCell,并对封闭的 Sheep 额外加分
  4. 对被封闭在内部的 Bears 生成一条“回到合法边界”的路径(只走 Occupied 的直线路径,带安全上限防止死循环)
  5. 触发 UI、音效、胜利判定(占领率 ≥ 阈值)

对应实现集中在:QixLite.cs(BFS 可达性、填充、计分、熊的回归路径构建)


3) 敌人系统:同一套规则层,不同的行为层

  • Sheep:封闭后作为计分目标
  • Wolves:矩形占位(默认 2×2,可调),更接近“体积移动”的碰撞与合法性检查
  • Bears:只在合法边界巡逻;随着计时事件分阶段提速,晚期允许走 Trail(难度曲线更明确)
  • Locusts
    • 达成前置条件(例如封闭次数、冷却期、并发上限)才尝试刷新
    • 在 Occupied 上移动,BFS 寻找可吃目标(不可吃边框)
    • 只剩最后一圈边界时会自毁并进入全局冷却,避免把玩法推到“无解”

对应实现集中在:QixLite.cs(Actor/行为逻辑) + LevelManager.cs(参数注入)


4) 关卡与流程:LevelManager + 可调参工程

LevelManager 提供 LevelConfig,把下面这些都变成可调参数:

  • Lives、单位数量(Sheep/Wolves/Bears)与狼占位大小
  • 玩家/敌人速度、计时器、胜利占领比
  • Locust:刷新间隔、全局冷却、最大并发数
  • 计分规则(每格/每 Sheep)

对应实现:LevelManager.cs(多关卡序列 + 胜利回调推进/回主菜单)


5) UI/音频/体验:把可玩性做完整

  • 主菜单两页弹窗流程与场景切换(防抖、可点击或超时继续):MainMenuUI.cs
  • HUD/结算弹窗/首关提示等游戏流完整性(项目内以 TMP/文本为主)
  • 音频:BGM 循环、事件音效钩子(胜利/死亡/得分/蝗虫等)
  • 反馈:抖动/特效/动画等(例如 ShakeObject.cs、尘土/胜利扫过等)

6) 版本发布和技术文档


开发过程中的关键难点(以及我怎么解决)

  • 边界与合法性规则最容易“写着写着就矛盾”
    我把“合法站立边界”定义成明确可验证的条件(例如必须与内侧 Empty 产生 8 邻接),并把“边框/内边界”规则统一起来,避免敌人与玩家走法分裂。

  • Trail 方向贴图与邻接判断
    早期 14-dir Trail 方向映射出错、且把无关邻居算进连通逻辑。我把轨迹连通性收敛为“只看 prev/next”,其它方向仅在 Occupied 情况下参与,从而稳定解决 sprite 朝向与分叉误判。

  • 视觉与规则耦合导致的滞后/错判
    增加 Visual-only 的邻接判断函数,把“高亮边缘”从“移动合法性”里拆出来,两套口径互不干扰。

  • 动态地形变化导致熊卡死
    Locust 啃地会改变地形,如果恢复路径强行要求每步都是 Occupied,容易陷入循环。我增加了救援模式(允许临时跨空格回到最近合法点)并加安全上限,保证最坏情况也能恢复。

这些问题的共性是:先锁定不变量(invariants),再用工具/日志把不变量变得可验证。这是我在客户端岗位里最常用的“保命方法”。


技术栈

  • Unity 6 / C#
  • Unity UI(GridLayoutGroup + Image)/ TextMeshPro
  • BFS / Flood Fill / 网格邻接 mask 选择(14-dir)
  • Android 构建与移动端输入调优(陀螺仪/分辨率)

代码入口

  • QixLite.cs:核心玩法(网格、输入、闭合填充、敌人、UI/音频钩子)
  • LevelManager.cs:关卡参数注入与流程推进
  • QixMinimal.cs:早期最小原型(Texture2D + flood fill 思路)
  • MainMenuUI.cs:菜单与弹窗流程
  • CloudLooper.cs / ShakeObject.cs:背景循环与交互反馈