> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wanyouxi.online/llms.txt
> Use this file to discover all available pages before exploring further.

# 游戏开发血泪史：那些没人告诉你的坑

> **摘要**：本文聚焦「游戏开发血泪史：那些没人告诉你的坑」，梳理核心概念、关键方法与落地实践。

**文档目标：** 汇总独立游戏开发中常见的“死法”与“坑”。
**核心价值：** 每一条建议背后，都是无数个废弃项目和熬秃的头顶。

## 1. 📉 范围管理：死于“再加个功能” (Scope Creep)

这是独立游戏死亡的 **No.1 原因**。

### ❌ 典型惨案

* **案例：** 你在做一个塔防。
* **想法：** “如果能联机就好了！” -> 花了 2 个月写网络同步。
* **想法：** “如果塔能装备道具就好了！” -> 花了 1 个月写背包和装备系统。
* **想法：** “如果能像 Minecraft 一样挖地形就好了！” -> 花了 3 个月重写地图系统。
* **结局：** 一年后，网络同步全是 Bug，装备系统不平衡，核心的“塔防”玩法却因为长时间没打磨，根本不好玩。项目太庞大，改不动，弃坑。

### ✅ 生存法则

* **🔪 MVP (最小可行性产品)：** 砍！砍到只剩核心。
  * 问自己：如果没有“联机”，这游戏能玩吗？能 -> 砍掉联机。
  * 问自己：如果没有“装备”，这游戏能玩吗？能 -> 砍掉装备。
* **🧱 验证核心：** 用方块和胶囊体（白模）把核心玩法做出来。如果白模状态下不好玩，加了美术特效也不会好玩。

***

## 2. 🙈 盲测：你不是你的玩家 (The Curse of Knowledge)

开发者有“上帝视角”，知道怎么玩。但玩家是“盲人”。

### ❌ 典型惨案

* **开发者视角：** “这关很简单啊，只要先造冰塔减速，再用火塔输出，最后用大招收尾就行了。”
* **玩家视角：** “这冰塔 500 金币太贵了，我全造了便宜的箭塔，结果怪跑太快，我死了。垃圾游戏，数值不平衡！”
* **结局：** 开发者觉得玩家笨，玩家觉得开发者蠢。

### ✅ 生存法则

* **🤐 扣掉空格键测试：** 找个朋友来玩，**你在旁边看着，绝对不许说话**。
  * 看他在哪里卡住？
  * 看他有没有漏看你的教程？
  * 看他是不是完全没发现那个“核心按钮”？
* **🎓 教程不仅是弹窗：** 最好的教程是关卡设计。参考《马里奥 1-1》。第一关不要给玩家 10 个塔，只给 1 个。强迫他学会用这 1 个，再给第 2 个。

***

## 3. 💾 存档与版本：隐形的杀手 (Save System & Versioning)

新手通常最后才做存档，然后发现代码根本改不动。

### ❌ 典型惨案

* **场景：** 游戏发售了 v1.0。玩家玩了 50 小时。
* **更新：** 你发布了 v1.1，增加了一个新属性 `Mana`。
* **灾难：** 玩家读取 v1.0 的存档，存档里没有 `Mana` 字段。数据解析报错，存档损坏，玩家 50 小时心血归零。Steam 差评如潮。

### ✅ 生存法则

* **📝 第一天就做存档：** 不要把数据分散在几百个脚本里。用一个 `GameData` 类统一管理。

* **🔢 版本号控制：** 存档文件头必须包含 `SaveVersion`。
  ```csharp theme={"theme":{"light":"github-light","dark":"github-dark"}}
  if (saveVersion < 1.1) {
      data.Mana = 100; // 给予默认值，防止空指针
  }
  ```

* **☁️ 云存档与本地防作弊：** 如果只是单机，简单的 JSON 加密（XOR 或 Base64）防君子不防小人即可，别花太多精力在反作弊上，好玩更重要。

***

## 4. 🌍 本地化：不要硬编码 (Localization)

不要在代码里写中文！不要在代码里写中文！

### ❌ 典型惨案

* **代码：** `uiText.text = "攻击力: " + atk;`
* **需求：** 游戏火了，要出英文版。
* **灾难：** 你需要查找全工程几千个 `.cs` 文件，把所有的中文字符串抠出来。而且 "攻击力" 在英文里可能是 "ATK" 也可能是 "Damage"，长度不一样，UI 爆框了。

### ✅ 生存法则

* **🔑 使用 Key：** 代码里写 `uiText.text = Localization.Get("ATTR_ATK") + atk;`。
* **📊 CSV 表格：** 维护一个 Excel/CSV。
  * `Key` | `CN` | `EN`
  * `ATTR_ATK` | 攻击力 | ATK
* **📏 UI 预留空间：** 英文通常比中文长，德文比英文还长。设计 UI 框时要预留 50% 的宽度冗余。

***

## 5. 📱 UI/UX：耗时 40% 的黑洞

很多新人觉得做游戏就是做战斗。其实做游戏一半时间在做 UI。

### ❌ 典型惨案

* **现象：** 战斗很爽。但是——
  * 没有暂停菜单。
  * 没有音量调节。
  * 分辨率改了 UI 就歪了。
  * 手柄无法在这个界面选中按钮。
  * 背包满了没有提示，装备掉了捡不起来。
* **结局：** 游戏被称为“半成品”。

### ✅ 生存法则

* **📐 UI 框架：** 使用 MVC 模式或专门的 UI 栈管理（入栈、出栈、弹窗覆盖）。不要手动 `SetActive` 乱飞。
* **📺 分辨率适配：** 永远在 Canvas Scaler 里设置 `Scale With Screen Size`。测试时把 Game 窗口拉成各种奇葩长宽比（带鱼屏、老式 iPad），看 UI 会不会重叠。

***

## 6. 🎨 视觉层级：什么更重要？ (Visual Hierarchy)

### ❌ 典型惨案

* **场景：** 地板纹理非常精细（4K石头纹路），子弹特效极其华丽（全屏光效）。
* **体验：** 玩家看不清怪在哪，看不清子弹在哪。一打起来满屏光污染，玩了 10 分钟眼睛瞎了。
* **原因：** 噪点太多，主次不分。

### ✅ 生存法则

* **👀 眯眼测试 (Squint Test)：** 眯起眼睛看你的游戏画面。
  * 你能一眼看到**玩家**在哪里吗？
  * 你能一眼看到\*\*威胁（敌人/子弹）\*\*在哪里吗？
  * 背景应该低对比度、低饱和度。
  * 交互物/威胁应该高对比度、高亮。
* **📉 信息做减法：** 伤害跳字如果每秒 50 个，就没人看了。合并显示，或者只显示暴击。

***

## 7. 📣 宣发：酒香也怕巷子深 (Marketing)

### ❌ 典型惨案

* **做法：** 闷头开发 2 年，发售当天在推特发了一条：“我游戏上线了！”
* **结果：** 销量 5 份（你自己买了一份，你妈买了一份）。

### ✅ 生存法则

* **🏪 商店页面是核心：** 在你游戏哪怕只做出了一个 Demo 的时候，就上架 Steam 页面（Coming Soon）。
* **💊 胶囊图 (Capsule Art)：** Steam 列表里那个小小的封面图，决定了点击率 (CTR)。花钱请专业画师画这个，比画游戏内的 UI 划算得多。
* **❤️ 愿望单 (Wishlist)：** 它是销量的倍增器。发售前没有 5000-10000 愿望单，基本就是暴死。

***

## 8. 🧠 开发者心理：不要在这个功能上死磕

### ❌ 典型惨案

* **纠结：** “这个跳跃的手感，我觉得还不够完美，我要再调第 100 版。”
* **现实：** 玩家根本感觉不出第 99 版和第 100 版的区别。
* **代价：** 你为了这个跳跃，耽误了怪物 AI 的开发。

### ✅ 生存法则

* **🏁 完成比完美更重要 (Done is better than perfect)。**
* **⚖️ 二八定律：** 80% 的效果只需要 20% 的时间。剩下 20% 的极致效果需要 80% 的时间。对于独立游戏，做到 85% 就够了，剩下的时间去打磨整体流程。

***

## 9. 🔊 声音设计：被忽视的 50% (The Silent Bug)

新手开发者最容易把声音留到上线前一天才加。

### ❌ 典型惨案

* **现象：** 你做了一个重锤打击的动作，画面很震撼，特效很足。但玩家觉得“软绵绵的”。
* **原因：** 音效太轻，或者音画不同步。
* **真理：** 所谓的**打击感**，30% 靠动画，20% 靠特效，**50% 靠音效**。

### ✅ 生存法则

* **🍊 Juice It Up：** 给每一个反馈都加上音效。点击按钮要有声音，打开菜单要有声音，金币飞入要有声音。
* **🎲 随机化音高 (Random Pitch)：** 机枪连射时，不要播放同一个 `.wav` 100 次。每次播放时把 Pitch 在 `0.9` \~ `1.1` 之间随机一下。这能让声音听起来不机械，像真的枪声。

***

## 10. ⌨️ 输入系统：别假设所有人都用 WASD (Input Hell)

### ❌ 典型惨案

* **场景：** 你在代码里写死了 `if (Input.GetKeyDown(KeyCode.W))`。
* **反馈：** 游戏上线第一天，法国玩家给了差评。
* **原因：** 法国键盘是 **AZERTY**，W 位置是 Z。他们想前进却不得不把手指扭成麻花。

### ✅ 生存法则

* **🎮 使用新输入系统 (Input System)：** 或 Rewired 插件。
* **🔧 支持改键：** 这是 PC 游戏的**标配**。如果没有改键功能，很多残障人士或特殊设备玩家根本玩不了。
* **🕹️ 手柄支持：** 即使是策略游戏，Steam Deck 用户也希望能用手柄玩。

***

## 11. 🧱 物理穿模：速度太快的锅 (Tunneling)

### ❌ 典型惨案

* **现象：** 你的狙击枪子弹速度设为 500。结果玩家发现子弹经常**穿过**墙壁，打不到怪。
* **原因：** 在这一帧，子弹在墙前；下一帧，子弹位置计算在墙后。由于没有“撞”到墙的碰撞体，物理引擎认为它只是瞬移过去了。这就是 **Tunneling (穿隧效应)**。

### ✅ 生存法则

* **🔦 射线检测 (Raycast)：** 对于极高速度的子弹，不要用刚体碰撞。直接发射一条射线，判定射线有没有打中东西。
* **⏱️ CCD (连续碰撞检测):** 如果必须用刚体，在 Rigidbody 设置里把 `Collision Detection` 改为 `Continuous`。但这比较耗性能。

***

## 12. 💰 经济崩坏：滚雪球效应 (Snowballing)

### ❌ 典型惨案

* **设计：** “为了奖励高玩，杀怪越快金币越多！”
* **结果：**
  * 高玩：杀得快 -> 钱多 -> 塔更强 -> 杀得更快。游戏变得毫无挑战，像割草。
  * 菜鸟：杀得慢 -> 钱少 -> 塔弱 -> 漏怪 -> 没钱补塔。游戏变得极其硬核，第一关都过不去。
* **结局：** 只有 1% 的人觉得好玩。

### ✅ 生存法则

* **🪀 橡皮筋机制 (Rubber Banding)：**
  * 给落后者补偿：连败奖励、低血量伤害加成。
  * 给领先者限制：杀怪收益递减、塔的升级价格指数级上升。
* **📉 负反馈循环：** 参考《马里奥赛车》。第一名吃到的是垃圾道具（香蕉皮），最后一名吃到的是无敌星。这能让所有人都能玩到最后。

***

## 13. 📱 平台移植：PC 的 UI 放不下手机 (Platform Constraints)

### ❌ 典型惨案

* **PC 版：** 鼠标悬停 (Hover) 显示技能详情。很方便。
* **移植手机：** 手机没有“悬停”操作。玩家手指按住是“点击”。
* **结果：** 手机玩家永远无法查看技能说明，只能盲选。

### ✅ 生存法则

* **👆 长按 (Long Press)：** 在手机上用长按代替悬停。
* **🔳 大按钮：** 鼠标可以点 20x20 像素的按钮，手指不行。手机按钮点击区域至少要 80x80 像素。

***

## 14. 🕸️ 联机大坑：状态同步 (Networking Nightmare)

再次强调，如果这是你的第一个项目，**千万别做联机**。

### ❌ 典型惨案

* **单机思维：** `Monster.HP -= 10;`
* **联机现实：**
  * 玩家A 开枪了。
  * 玩家B 网络延迟 200ms，还没看到玩家A开枪。
  * 玩家A 屏幕上怪死了。
  * 玩家B 屏幕上怪还活着，并且把玩家B打死了。
  * **结果：** 玩家B 怒砸键盘，“挂壁游戏！”

### ✅ 生存法则

* **🔄 状态分离：** 必须区分 **Server State (权威状态)** 和 **Local State (预测状态)**。
* **🤖 确定性 (Determinism)：** 保证同样的输入，在所有机器上产生同样的结果（这在浮点数运算下极难做到）。
* **🛑 结论：** 做单机吧，真的。
