游戏设计:原型与开发 18:Unity入门的第一课
- [一、1GB 的下载,和一个有点浪漫的选择](#一、1GB 的下载,和一个有点浪漫的选择)
-
- [Unity 不是一个软件,是一个"组装车间"](#Unity 不是一个软件,是一个"组装车间")
- [二、为什么选 Unity?四个理由,其中一个很可爱](#二、为什么选 Unity?四个理由,其中一个很可爱)
- 三、为什么是 C#?一场关于"弱类型"的吐槽
- 四、作者的教学法:三步,其中一步是"故意坑你"
-
- [90% 的 Bug 是手误](#90% 的 Bug 是手误)
- 五、首次运行:先玩,再干活
- 六、小结
一、1GB 的下载,和一个有点浪漫的选择
这一章开始,作者终于不再讲思维体操了------要装软件了。
第一句话很实在:Unity 安装包 1GB 以上,网速快几分钟,网速慢几小时。写完这段话的时候,主版本还是 Unity 4,版本号大概是 4.x.y 那种"永远在更新"的形态。
然后是那句藏在提示框里的细节:Unity 免费,但需要许可;第一次运行必须联网激活。这大概是很多新手的第一个"卡住的地方"------不是不会写代码,是没网。
Unity 不是一个软件,是一个"组装车间"
作者对 Unity 的定位非常准确:它本身是一个组装程序。素材大多在别处生产:
#mermaid-svg-j1TKswiffKn98Od5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-j1TKswiffKn98Od5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-j1TKswiffKn98Od5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-j1TKswiffKn98Od5 .error-icon{fill:#552222;}#mermaid-svg-j1TKswiffKn98Od5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-j1TKswiffKn98Od5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-j1TKswiffKn98Od5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-j1TKswiffKn98Od5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-j1TKswiffKn98Od5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-j1TKswiffKn98Od5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-j1TKswiffKn98Od5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-j1TKswiffKn98Od5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-j1TKswiffKn98Od5 .marker.cross{stroke:#333333;}#mermaid-svg-j1TKswiffKn98Od5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-j1TKswiffKn98Od5 p{margin:0;}#mermaid-svg-j1TKswiffKn98Od5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-j1TKswiffKn98Od5 .cluster-label text{fill:#333;}#mermaid-svg-j1TKswiffKn98Od5 .cluster-label span{color:#333;}#mermaid-svg-j1TKswiffKn98Od5 .cluster-label span p{background-color:transparent;}#mermaid-svg-j1TKswiffKn98Od5 .label text,#mermaid-svg-j1TKswiffKn98Od5 span{fill:#333;color:#333;}#mermaid-svg-j1TKswiffKn98Od5 .node rect,#mermaid-svg-j1TKswiffKn98Od5 .node circle,#mermaid-svg-j1TKswiffKn98Od5 .node ellipse,#mermaid-svg-j1TKswiffKn98Od5 .node polygon,#mermaid-svg-j1TKswiffKn98Od5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j1TKswiffKn98Od5 .rough-node .label text,#mermaid-svg-j1TKswiffKn98Od5 .node .label text,#mermaid-svg-j1TKswiffKn98Od5 .image-shape .label,#mermaid-svg-j1TKswiffKn98Od5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-j1TKswiffKn98Od5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-j1TKswiffKn98Od5 .rough-node .label,#mermaid-svg-j1TKswiffKn98Od5 .node .label,#mermaid-svg-j1TKswiffKn98Od5 .image-shape .label,#mermaid-svg-j1TKswiffKn98Od5 .icon-shape .label{text-align:center;}#mermaid-svg-j1TKswiffKn98Od5 .node.clickable{cursor:pointer;}#mermaid-svg-j1TKswiffKn98Od5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-j1TKswiffKn98Od5 .arrowheadPath{fill:#333333;}#mermaid-svg-j1TKswiffKn98Od5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-j1TKswiffKn98Od5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-j1TKswiffKn98Od5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j1TKswiffKn98Od5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-j1TKswiffKn98Od5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j1TKswiffKn98Od5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-j1TKswiffKn98Od5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-j1TKswiffKn98Od5 .cluster text{fill:#333;}#mermaid-svg-j1TKswiffKn98Od5 .cluster span{color:#333;}#mermaid-svg-j1TKswiffKn98Od5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-j1TKswiffKn98Od5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-j1TKswiffKn98Od5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-j1TKswiffKn98Od5 .icon-shape,#mermaid-svg-j1TKswiffKn98Od5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j1TKswiffKn98Od5 .icon-shape p,#mermaid-svg-j1TKswiffKn98Od5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-j1TKswiffKn98Od5 .icon-shape .label rect,#mermaid-svg-j1TKswiffKn98Od5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j1TKswiffKn98Od5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-j1TKswiffKn98Od5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-j1TKswiffKn98Od5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MonoDevelop / IDE
写 C# 代码
Unity
组装 · 布局 · 编译
MAYA · 3ds Max · Blender
建模型与材质
Photoshop · GIMP
做贴图与 UI
Pro Tools · Audacity
剪音频
Windows
macOS
Web
iOS / Android
更多平台
图说 :这张图解释了 Unity 的"中心化"角色------它不生产内容,它编排内容。左边四个方框代表你的工作流外围,右边五个方框代表同一份工程能导出的平台。理解这一点,你才不会指望在 Unity 里"画"出一个角色------那是建模软件的事。
二、为什么选 Unity?四个理由,其中一个很可爱
作者列了四条,我按"可信度"重排一下:
① 免费。 免费版就能开发兼容 OSX、Windows、Web、Linux、iOS、Android、BlackBerry、Windows Phone、Windows Store 的游戏。专业版 1500 美元(或 75 美元/月),而学生一年的教育许可大约只要 150 美元------打 1 折。注意:教育许可不允许直接发售作品,想卖钱还得升级商业版。
② 一次编写,到处部署。 同一套源码、同一套源文件,导出多个平台。作者特意点明:这正是"Unity"这个名字的由来。
③ 社区。 几十万开发者在用,论坛很热。
④ "它非常出色!" ------ 作者和学生的玩笑是:Unity 有一个"变出色(make it awesome)按钮"。严格来说不存在,但很多功能确实只是勾一个复选框,画面立刻好看。因为 Unity 已经替你解决了一堆硬骨头:
| Unity 内置解决的难题 | 如果你自己写,要花多久 |
|---|---|
| 碰撞检测 | 数学 + 空间划分,够写一章 |
| 物理模拟 | 够写一本书 |
| 寻路(Pathfinding) | 够写一篇论文 |
| 粒子系统 | 够写一个学期 |
| 绘制调用批处理(Batching) | 够调一周性能 |
| 着色器 | 够学一门新语言 |
| 游戏主循环 | 这是"引擎"的本体 |
这张表的潜台词是:别把时间花在已经有答案的问题上。你的时间应该花在"这个游戏为什么好玩"上。
三、为什么是 C#?一场关于"弱类型"的吐槽
Unity 支持三种语言:UnityScript(JavaScript 变体)、C#、Boo。作者说得很直白:几乎没人真的用 Boo,所以基本是二选一。
他对 JavaScript 的批评很有画面感:弱类型意味着你可以建一个叫 bob 的变量,然后往里塞数字、单词、整本小说、甚至游戏主角。于是"Unity 永远也不知道 bob 到底代表什么"。这种自由让脚本变得乏味,也让你用不上现代语言的强大特性。
C# 则是 2000 年微软为对抗 Java 而做的:把 Java 的现代特性揉进 C++ 程序员熟悉的语法里。老手能得到委托、动态绑定、运算符重载、lambda、LINQ;新手只需要知道一件事------用 C# 入门,会把你养成更合格的程序员。
这不是空口白话。作者在南加大教书时做过对照:学 C# 的学生,做出的原型水平更高、编码习惯更强、对自己的能力也更自信。
| 维度 | UnityScript | C# |
|---|---|---|
| 类型系统 | 弱类型,变量随时变脸 | 强类型,编译期就拦住你 |
| 上手速度 | 快 | 稍慢 |
| 长期收益 | 容易写出"能跑但说不清"的代码 | 习惯、结构、可维护性 |
| 作者课堂结论 | 原型水平较低 | 原型水平更高、更自信 |
一个必须澄清的迷思:三种语言跑得一样快
有经验的程序员可能会想:C# 是编译型,JS 是解释型,那 C# 应该更快吧?
作者的答案是:在 Unity 里,一样快 。因为不管你保存哪种脚本,Unity 都会先把它转成通用中间语言 CIL,再把 CIL 编译成机器码。
#mermaid-svg-TEm7zC6KTp02AQCL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TEm7zC6KTp02AQCL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TEm7zC6KTp02AQCL .error-icon{fill:#552222;}#mermaid-svg-TEm7zC6KTp02AQCL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TEm7zC6KTp02AQCL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TEm7zC6KTp02AQCL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TEm7zC6KTp02AQCL .marker.cross{stroke:#333333;}#mermaid-svg-TEm7zC6KTp02AQCL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TEm7zC6KTp02AQCL p{margin:0;}#mermaid-svg-TEm7zC6KTp02AQCL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TEm7zC6KTp02AQCL .cluster-label text{fill:#333;}#mermaid-svg-TEm7zC6KTp02AQCL .cluster-label span{color:#333;}#mermaid-svg-TEm7zC6KTp02AQCL .cluster-label span p{background-color:transparent;}#mermaid-svg-TEm7zC6KTp02AQCL .label text,#mermaid-svg-TEm7zC6KTp02AQCL span{fill:#333;color:#333;}#mermaid-svg-TEm7zC6KTp02AQCL .node rect,#mermaid-svg-TEm7zC6KTp02AQCL .node circle,#mermaid-svg-TEm7zC6KTp02AQCL .node ellipse,#mermaid-svg-TEm7zC6KTp02AQCL .node polygon,#mermaid-svg-TEm7zC6KTp02AQCL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TEm7zC6KTp02AQCL .rough-node .label text,#mermaid-svg-TEm7zC6KTp02AQCL .node .label text,#mermaid-svg-TEm7zC6KTp02AQCL .image-shape .label,#mermaid-svg-TEm7zC6KTp02AQCL .icon-shape .label{text-anchor:middle;}#mermaid-svg-TEm7zC6KTp02AQCL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TEm7zC6KTp02AQCL .rough-node .label,#mermaid-svg-TEm7zC6KTp02AQCL .node .label,#mermaid-svg-TEm7zC6KTp02AQCL .image-shape .label,#mermaid-svg-TEm7zC6KTp02AQCL .icon-shape .label{text-align:center;}#mermaid-svg-TEm7zC6KTp02AQCL .node.clickable{cursor:pointer;}#mermaid-svg-TEm7zC6KTp02AQCL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TEm7zC6KTp02AQCL .arrowheadPath{fill:#333333;}#mermaid-svg-TEm7zC6KTp02AQCL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TEm7zC6KTp02AQCL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TEm7zC6KTp02AQCL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TEm7zC6KTp02AQCL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TEm7zC6KTp02AQCL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TEm7zC6KTp02AQCL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TEm7zC6KTp02AQCL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TEm7zC6KTp02AQCL .cluster text{fill:#333;}#mermaid-svg-TEm7zC6KTp02AQCL .cluster span{color:#333;}#mermaid-svg-TEm7zC6KTp02AQCL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TEm7zC6KTp02AQCL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TEm7zC6KTp02AQCL rect.text{fill:none;stroke-width:0;}#mermaid-svg-TEm7zC6KTp02AQCL .icon-shape,#mermaid-svg-TEm7zC6KTp02AQCL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TEm7zC6KTp02AQCL .icon-shape p,#mermaid-svg-TEm7zC6KTp02AQCL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TEm7zC6KTp02AQCL .icon-shape .label rect,#mermaid-svg-TEm7zC6KTp02AQCL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TEm7zC6KTp02AQCL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TEm7zC6KTp02AQCL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TEm7zC6KTp02AQCL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} C# 脚本
CIL
通用中间语言
UnityScript / Boo
机器码
运行时
图说 :三条输入箭头最终汇进同一个 CIL 节点,这就是"速度一样"的原因------它们根本不是直接跑的。理解这张图还有个额外好处:以后看到"某语言更快"的营销话术,你会先问一句"它编译到哪一层"。
四、作者的教学法:三步,其中一步是"故意坑你"
掌握新语言不容易。作者打了个很妙的比方:学到某个阶段,你会像"学了一学期西班牙语就去看西语肥皂剧"------每个词都认识,整句话不知所云。他所有的学生半个学期后都有这种感觉,但学期结束时都会变得自信。
他的教学法只有三步:
- 概念介绍:写代码之前,先说清楚"要做什么、为什么这样做";
- 引导性教程 :一步步做,全程编译和测试,边做边抓 Bug;
- 重复练习:先带你做一个敌人类型,再让你自己做另外三个。
第 2 步里藏着一句很有胆量的话:"笔者甚至会给你制造一些 Bug",让你提前认识它们长什么样。
这其实是"疫苗式教学":在安全的环境里感染一次,真上战场时就有抗体了。
90% 的 Bug 是手误
作者说他帮学生改 Bug 改出了肌肉记忆,现在能秒定位。常见的手误只有三类:
| 类型 | 例子 | 编译器的反应 |
|---|---|---|
| 拼写错误 | tramsform 写成 transform 的亲戚 |
找不到标识符 |
| 大小写错误 | Variable / variable / variAble |
在 C# 眼里是三个词 |
| 漏写分号 | int x = 1 后面没 ; |
报错往往出现在下一行 |
为什么 C# 用分号而不是句号?因为句号已经被小数点占用了,还被"点语法"占用了:varName.subVarName.SubSubVarName。
漏分号这个坑最阴险,看个例子:
csharp
void Start()
{
int score = 0 // ← 少了分号
Debug.Log(score); // 编译器会在这里报错,但问题在上一行
}
这段代码在说明什么 :编译器的报错行号不等于错误行号。学会"往上找一行",能省掉大量抓头发的时间 🧠。
再往后,作者会布置一个真正上强度的作业:四周内,逼真还原一款经典游戏的机制与体验------《超级马里奥》《银河战士》《恶魔城》《口袋妖怪》,甚至初代《塞尔达传说》。
关键不是复刻,而是那句心理转变:
从"我在学习这本教程",变成"我想做成这件事情------现在我需要怎么做?"
五、首次运行:先玩,再干活
装完、激活许可(建议先激活免费版,把 30 天 Pro 试用留到第 34 章做 QuickSnap 时再用,因为那时需要漂亮的反射和着色器),Unity 会自动打开演示项目 AngryBots。
这个项目加载要几秒,期间窗口可能看起来假死------别慌,等它。
进游戏后按提示玩:
- WASD 或方向键移动;
- 枪口永远指向鼠标;
- 左键开枪;
- 想在圆形舱门前站几秒才开;
- 有些地方要站到电脑前,让红色电线变绿。
玩的时候作者让你注意三样东西:
| 效果 | 描述 | 谁能看到 |
|---|---|---|
| A 景深 | 一部分清晰,一部分模糊 | 仅 Pro |
| B 地板反光 | 尤其激光瞄准器的倒影 | 仅 Pro |
| C 动态雨滴 | 室外地面上的雨 | 免费版也能看到 |
这就是免费版与专业版"为数不多的区别之一"。作者的态度很务实:学习阶段,免费版够用。
还有两个技术点值得记一笔:
- 动画合成:角色可以一边朝一个方向射击、一边朝另一个方向移动;
- AI 寻径:敌人能绕过室内障碍找到你。
把游戏编译到网页
停止运行 → File > Build Settings... → 选 Web Player → 勾 Offline Deployment → 保存为 AngryBotsWebBuild → 等它处理完,浏览器自动打开。
作者的原话是"这样就大功告成了"。半个小时的下载 + 几次点击,你就拥有了一个能发给朋友看的网页版游戏。
最后一步:把窗口摆好
Unity 允许你自定义面板布局。右上角的 Layout 菜单里有一堆预设,本书的示例统一使用 2 by 3 。菜单里还有 Save Layout...、Delete Layout...、Revert Factory Settings。
别小看这一步。后面所有教程的截图都基于同一套布局------布局一致,你的眼睛才不用每次重新找东西。
六、小结
这一章其实干了四件事:
- 装好环境,拿到许可;
- 说清楚"为什么是 Unity、为什么是 C#"------两个选择都有可验证的理由,而不是信仰;
- 用 AngryBots 让你先体验"完成度",再回头学"怎么做";
- 把窗口摆成全书统一的样子。

如果只能记一句话,我选作者那句自嘲式的教学承诺:
我会故意给你制造 Bug,这样你以后遇到自己的 Bug 时,处理起来会更简单。
毕竟,游戏开发这门手艺,一半是创造,一半是和自己的手误搏斗 🐛。