前导
所有想法都能落地实现成功能,成系统吗?
从接触编程伊始,这个想法就一直萦绕在我心头
特别是对于广义上的游戏开发方向(包括但不限于玩法实现,引擎开发,图形学开发等),这种实践频率极高的领域
在工业生产中很多项目组大都处于以下情况:
PM也好,策划也好,制作人也好,对于功能的实现,想法的设计很多都停留在以下三种状态:”现实中/历史上有成功的案例“,”市面上的产品都是这么做“,”应该能做吧,应该可行吧“
程序员,甚至很多十年以上经验的老程序员,从上游拿到需求后,简单分析一下或不分析(大多数业务不需要动脑),就开始凭借经验(猜,赌),自己没有经验的凭借别人的经验,模棱两可地”和出来一滩稀泥“,然后就扔进版本里进行迭代(美其名曰:敏捷)
对于想法的实现,从来就没有形成一套方法论/认知。也许你会说,工作中写出来为大,是否可行不是我这个环节该管的事情,那我衷心地希望你能一直开心下去
实际上,这便是软件工程中最核心、也是最容易被忽视的环节——从模糊意图到确定性系统的认知鸿沟
大多数生产环境处于一种“经验主义 + 迭代试错”的混沌状态,这在上层软件开发可能会造成困扰,但在追求绝对确定性的图形学、引擎和底层系统开发中却是致命的
试图用感性的思维去思考理性的事情是编程的大忌
综上所属,所以本篇文章的主题就是广义的如何从想法到实现的方法论
分析
任何想法,只要能被拆成“有限步骤 + 明确状态变化“,就一定可以用代码实现,反过来说:如果你无法描述“它一步步怎么做”,那就还不是代码层面的想法
也就是说,要先建模
写代码,本质就是把现实/想法 -> 转成模型 -> 再让模型运行
在讨论方法论之前,先承认一个物理现实:不是所有想法都值得建模,也不是所有的想法都能在有限算力/人力内实现
我们可以将广义的“游戏开发想法”分为三个象限
| 象限 | 类型 | 特征 | 程序员的态度 |
|---|---|---|---|
| 第一象限 | 市场/体验想法 | “我想做一个像 WOW 但又有 MC 建造自由的游戏” | 不可直接建模,这是愿景,不是输入参数。需要拆解 |
| 第二象限 | 工程确定性想法 | “我要一个边缘光描边,宽度不受透视影响” | 可建模。这是数学和GPU管线的确定性推导 |
| 第三象限 | 未知探索性想法 | “我想让NPC的行为看起来像真人一样有情绪记忆” | 需降维建模。必须用有限状态机、效用AI或GOAP将不可计算的“情绪”降维成可计算的“数值权重” |
方法论的第一原则:将第一、三象限的想法,通过形式化描述,强制转化为第二象限的数学/逻辑问题。如果不能转化,那就是不可实现,或者只能通过“堆美术资源硬骗眼睛”来实现(这也是一种实现路径,但不是工程路径)
判断方法
1. 能不能写出“流程”
- 输入是什么
- 输出是什么
- 中间过程能不能一步步描述
比如,做一个自动整理文件的工具
遍历目录 -> 判断文件类型 -> 按类型分类 -> 移动文件
这就是典型的可编程流程
再比如,我想让程序理解我的心情
- 什么是”心情”(没有定义)
- 输入是什么
- 如何判断
这时候需要把它转化成
输入:文本
-> 情感分析模型
-> 输出:正面/负面/中性
这样才进入“可实现区间”
2. 能不能定义数据结构
程序的本质是“数据 + 操作”
这个想法里的东西能不能用数据表示
| 想法 | 数据表示 |
|---|---|
| 游戏角色 | struct/class |
| 行为树 | 树结构 |
| UI界面 | 组件树 |
| 编译器 | token/AST |
如果无法定义成数据结构,那说明想法还在“概念层”,还没落地
3. 有没有已知理论/现有方案
这个问题所属领域有没有现成算法/论文/开源实现
| 想法 | 对应领域 |
|---|---|
| 路径规划 | 图论/A* |
| 渲染 | 图形学 |
| AI行为 | 行为树/FSM |
| 编译器 | 语法分析 |
4. 能不能“手算一遍”
不用电脑,用纸模拟一遍
比如做一个排序算法
输入:[3, 1, 2]
能不能一步步变成[1, 2, 3]
如果能手动执行,则一定能写成代码;如果卡住,就说明逻辑不完整
5. 物理不可能或信息不足
有些想法本质上做不到
- 预测未来(无信息)
- 读取别人脑子(无输入)
- 完美判断任意程序是否停机(Halting Problem)
结论
也就是说,先建模
写代码,本质就是把现实/想法 -> 转成模型 -> 再让模型运行
示例
定义世界里有什么
也就是数据结构
struct Player {
int hp;
Vector3 position;
Weapon weapon;
};
其实就是把现实中的玩家抽象成这些字段
定义会发生什么
就是逻辑/算法
if (player.hp <= 0) {
Die();
}
定义怎么变化
状态流动
player.hp -= damage;
系统如何随时间演化
如果不建模,直接写代码,就像没有定义世界规则,代码就变成随机拼接(就是赌和猜)
- 能不能画结构图(类图/数据关系)
- 能不能写出状态变化(谁改谁)
- 能不能手动模拟一帧
只要这三点成立,基本一定能写出来
建模
建模 = 数据结构 + 规则 + 状态变化