In a Jam
我参加了大学社团举办的一场Game Jam,这是我发生的变化。
By Ice_Kube | 2026-03-01
几周前,我学校的游戏开发社发起了一个类Game Jam活动。这个活动与一般Game Jam不同,它并不规定主题,并且主要面向那些没有处理较大体量项目的经验的大一新生。
本来我是打算自己带队的,因为我有整过几个大型项目,而且我也想做个自己设计的游戏。
但计划赶不上变化。
当人们在组建自己的队伍的时候,我突然病倒,全天卧床,连QQ都没去看一眼,更不用说上线去拉人组建我自己的队伍了。
最后,只剩下一个队伍仍然需要人,而那个队伍准备制作一个塔防类游戏。
行吧。就当我运气不好了。
不然我还能去哪?报都报名了,难道退出吗?
正式开始之前,主策、主美、组长和我开了个小会,大致聊了一下整个项目各种未敲定的细枝末节的内容。 组长认为我编程水平比较稳,于是让我负责带领程序组。大概就这些,没多大阵仗。
接着是全组的大会议,我制定了 Git 的使用规范。
如果你没听过Git:Git 是一个版本控制工具,方便一个团队的成员协同写代码。但如果没有明确的使用规范,
代码库,也就是”Git 仓库”,很快就会乱成一锅粥,开发越往后越难推进。我后来得知另一支队伍就踩了这个坑。
放在平时的其他项目里,这已经很让人头大了;而在Game Jam这种冲刺项目里,这完全不可接受。
而且,想要高效使用 Git(避免冲突、保持提交历史整洁)是需要学习成本的。在短短七天的赛程里,要求每个人花好几天去上手显然不现实。
于是我决定:我将全权掌控main分支。任何人都不能直接向main分支直接推送,除了美术,因为他们只提交素材,不碰代码。
任何程序想要合并代码,都必须经过我的审核。
项目结束后,他们将其戏称为“独裁”,好像…还挺准确的。
项目第一天,我实现了一个EventBus系统,用于不同脚本之间的通信。
一般情况下,如果脚本 A 要和脚本 B 通信,A 必须知道 B 的存在才行,否则程序就会报错。就像你如果要给人打电话,你得先知道那个人的电话号码。
但是如果使用EventBus系统,A 不需要知道 B 的“电话”,它只需把数据丢给系统,系统会自动把消息转发给所有正在“监听”这类数据的脚本。
就像你让一家公司去“给所有名叫李华的人打电话留言”,而你根本不需要知道究竟有没有李华这号人存在。
引入这套系统是为了解耦。我们需要让脚本在不产生错综复杂的依赖关系的情况下进行通信,并保持代码库易于扩展。 随着项目规模扩大,这种系统带来的优势会越来越明显。
既然我引入了一套大家都没用过、但又要频繁调用的系统,我迅速写了一份文档说明用法,并附带了一些可以直接
Ctrl-C Ctrl-V进项目的通用代码模板。
第一天到第五天进展顺利。
Git 的提交历史非常密集,在巅峰时期,它长得简直跟个地铁线路图似的。

当然,这五天也不是一帆风顺:Bug 时不时冒头,Git 冲突导致有人得重写代码,代码注释不明甚至没注释,文件编码错误……
好在大家学得很快。我在群聊里指出该做什么、不该做什么后,他们都能迅速修正。
除了一个人。
第五天晚上,我天塌了。
核心系统之一,建筑系统,终于被标记为“完成”并合并到了main分支。此时全队大部分人都在等这个系统。
这个系统的开发者在群里几乎完全不说话。
行吧,沉默也不一定代表真有问题,只要能准时产出能用的程序就行。
我将代码pull(拉取)下来,开始整理逻辑,准备将其并入系统。然而,摆在我面前的却是一大坨根本用不了的屎山。
技术层面上来说,代码确实 能跑,但没有任何稳定性可言。控制流混乱不堪,职责边界模糊。 大量逻辑内部自相矛盾——那种矛盾,只有在 AI 生成的代码从未经过人工审查时才会出现。 有些函数乍一看很合理,但当你追踪它们的状态时,会发现它们永远无法产生正确的结果。 另一些部分则悄无声息地违反了整个架构所依赖的前提假设。 要调试这段代码,意味着我得去逆向推解一种可能根本不存在的“意图”。
这段代码的问题不仅在于难以维护,它简直就是耦合地狱 —— 完全没有预留任何接口,所有系统强耦合,牵一发而动全身。
而且,我在群里反复强调的问题——文件编码错误、注释不清——在他的代码里简直满地都是。
更离谱的是,在使用我的 EventBus 时,只需要把文档里的通用代码复制粘贴进去就能用, 但我发现那些通用代码里居然出现了毫无意义的注释,这只能说明一件事:他把代码全权交给了 AI,完全没有自己检查。
此时,距离提交只剩下两天。
那天晚上,我决定放弃抢救,直接丢弃这个系统,整个重写。
第六天成了紧急重构日。数据流从头重新定义,交互边界重新划分,整套系统围绕可维护的逻辑和可预期的状态切换重新实现。
说人话就是:我用他代码里还能用的那点逻辑,做了一个新的建筑系统。
当新版本重新接入项目时,测试人员已经在准备进行全天的压力测试了。
第七天是纯粹的压力,无论是对程序还是对我们。
两名测试员从早到晚进行连续压力测试。所有人都全程在线,Bug 一冒出来就立刻修复。 在最后剩下不到 10 小时的时候,第一轮测试直接搞出了20多个 Bug。 每一次修复都可能引入新的问题。每一次改动都必须立即合并、编译、重新测试。那一天的Git记录简直让人心肌梗塞。
全程没人离开过椅子。
最终,我们在截止时间前 30 分钟提交了最终版本。
那个 48 小时前还无法使用的系统,现在正常运行。
芜湖。

提交完最终版本,所有人都松了口气,开始在群里闲聊。其中一个程序员说,要不是我的 EventBus 系统,我们根本不可能在截止前做完。这套系统大幅减少了潜在 bug,也降低了脚本间通信时的沟通成本,省了很多工作量。
它还让大家能独立实现各自的功能,而不用担心弄坏别人的逻辑。
但我的工作不是一切。这可不是什么一人救世的超级英雄电影。
我不会在 Unity 里做 UI —— 组长负责了这个系统,搭了一套相当复杂的 UI 系统,我不确定如果当时是我来做的话,能不能做得更好。
另一个程序员负责了最复杂的系统之一:敌人系统和会躲在墙后射击的弓箭手 NPC。
我确实在我写的 NPC 系统里预留了一个给他用的接口。但他没用,而是自己另写了一套 NPC 系统。
……好吧,至少是跑起来了。主要问题还是在于我没跟他沟通清楚。
还有,得益于我们策划写的详细,清晰的文档,我们没有像其他一些队伍那样,为了实现策划的需求而反复重写。此外,他还负责设计了我们的游戏地图。
我还要说说我们的美术 —— 没有他们的素材,游戏不可能做得出来。他们交付的角色和场景素材质量够高,完全不需要返工重做。
最后要感谢那两位测试员在最后一天的付出,没有他们,游戏肯定到处是 bug 没法玩。在测试间隙,他们还优化了地图,让游戏体验明显变好了。
不过,是不是忘了个人?
做建筑系统那人呢?
Section titled “做建筑系统那人呢?”第五天那事发生后,我作为实际负责人,告诉他我会接管建筑系统的后续维护工作。
我没有直接说他的代码”不能用”,只说了他现在不需要再写程序了,等到测试阶段加入测试员去做测试就行。
但他没有加入测试。
或者说,在接下来的几天里,他彻底消失了。
在游戏提交之后,大家还在群里聊得起劲,他私信了组长,在私信里情绪崩溃,发了一堆自暴自弃的话,给组长整不会了。
然后他就退了群,可能也把组长给拉黑了。
在此声明:我从来没有在群里明说过他代码有问题,也从未在群里提过他的名字。我只有在第五天晚上,压力爆炸的情况下,在组长的私信里发了几句牢骚。
我可没有在群里或者他的私信里说过任何针对他的话。
而关于让他别写程序这事:
有一说一,他并没有真的弄坏项目,他只是没有完成他的工作而已。
但当时只剩48小时了,我不能冒着再整一次这种大活的风险,所以他不能继续写程序。
这不是针对个人,我跟他无怨无仇。
我学到了什么?
Section titled “我学到了什么?”永远与队友保持沟通
Section titled “永远与队友保持沟通”我本来搭了一套高效且可扩展性强的基础 NPC 系统。但另一个程序员自己写了一套新的。
基本上是因为我没沟通到位,导致了重复劳动。他重写了一遍基础系统,而其他人还要面对两套 NPC 系统之间的兼容性问题。
此外,如果我能跟最初负责建筑系统的那个程序多沟通,也许可以避免那个事故
或者,至少我能早点发现问题,不至于最后搞成那种灾难。
永远不要盲目信任AI
Section titled “永远不要盲目信任AI”在急转直下那里,问题并不在于使用 AI,而在于盲目相信 AI 而不审查输出结果。
在重构系统时,我也大量使用了 AI,否则我当然不可能在一天内写出那种规模的程序。但我仔细阅读了它生成的每一行程序。在接受它提供的代码之前,我确保自己理解了每一段逻辑。
AI 只是一个工具,它的上限取决于使用者。
永远不要忽略项目架构
Section titled “永远不要忽略项目架构”在这种时间紧的项目里,返工次数越少越好。
EventBus 系统让大家可以并行工作而互不干扰。
Git 规则意味着合并过程不会演变成一场灾难。
策划的详细文档让所有人都知道”完成的功能”长什么样。
这些东西的构建成本都不高,但它们带来的回报远超成本。
一些写不进正文的小事
Section titled “一些写不进正文的小事”-
EventBus 系统不是我设计的。我从 GitHub 上找了一个现成的程序,然后稍微进行了一点修改,加了两个原版没有的功能:
优先级队列和事件取消。
-
游戏需要一个加载动画。所以我用
Unity Shader Graph做了一个简单的Dissolve Shader。
纯粹是出于个人爱好,毕竟我对图形学挺感兴趣。
而且这效果也挺cool。