跳转至

Ludo Atlas · 引擎轨道 · Unity

引擎轨道。定位:Unity 轨道工程手册,覆盖组件心智模型、脚本生命周期、数据资产、包生态、版本控制与多平台构建。 配套:《技术实现手册》·《美术与音频手册》·《制作管理手册》·《小游戏开发手册》。


1. 定位与选型

一句话定位:Unity 是组件化、C# 脚本驱动、生态存量最大的通用引擎。它不挑游戏类型,挑团队工程能力:编辑器把拼装成本压得很低,项目一大,结构、性能与协作的问题全要自己兜住。

适合:

  • 中小团队与独立开发者的第一款商业作品:文档、问答、教程的检索成本在同类引擎里最低。
  • 一次开发、多平台发行:桌面、移动、主机、Web 共用一套工程与内容。
  • 2D 与中低模 3D 项目:2D 工作流与 3D 管线在同一编辑器里,混合项目不用换工具。
  • 玩法与数值迭代频繁的原型:编辑器内改完立即验证,循环很短。

需要三思:

  • 高保真 3D 与超大场景:这是 Unreal 的主场,别用工程成本硬扛美术缺口。
  • 极致轻量的 2D 小项目:Godot 或 Web 技术栈的工程面更小。
  • 深度改造引擎底层:Unity 核心闭源,可定制的是上层,底部动不了。

跨引擎取舍收口成四行(其余轨道见 docs/engines/):

项目画像 常规选择
通用商业项目、需要招人与外包生态 Unity(本页)
要求完全开源、愿意读改引擎源码 Godot 或自研引擎
高保真 3D、大团队工业流程 Unreal
纯 Web 交付、页面级轻量玩法 Web 技术栈

选型检查清单:

  • 目标平台里有没有 Web 或小游戏?有,先验证包体与加载,再决定(§3.3)。
  • 谁维护构建与版本控制?没有专人,先把 §2.4 的约定立起来。
  • 这是 2D 还是 3D 项目?决定后统一相机、光照与素材规格,不要两种做法混着来。
  • 团队的 C# 与架构水平如何?Unity 项目的主要技术债来自代码组织,不是引擎本身。

2. 生态与工程结构

2.1 工程目录结构

目录 内容 进版本库 说明
Assets/ 场景、脚本、Prefab、材质、模型、音频等项目内容 是 工作区,全部内容产在这里
Packages/ 依赖清单与本地嵌入包 清单与本地包进 依赖用清单声明,不要手动拷贝源码充当依赖
ProjectSettings/ 渲染、输入、物理、质量等工程级配置 是 团队协作的一部分,改动要评审
Library/、Temp/、Logs/ 导入缓存、临时文件与日志 否 本机可重建,提交只会制造冲突与噪音

2.2 组合心智模型

  • GameObject 是空容器,本身没有任何功能;功能全部由挂上去的组件提供:渲染、碰撞、音频、自定义脚本都是组件。
  • 一切组合都是往容器上拼零件:一个角色等于变换、碰撞、动画加若干行为脚本。没有继承树,只有拼装,所以「这个功能放哪」的答案通常是「新写一个小组件」。
  • 场景是对象的运行舞台,同时承担摆放与串联的角色。把场景当配置与挂载表,重逻辑不要长在场景里。
  • Prefab 是可复用的对象模板:在场景里搭出原型,存成资产,再从模板实例化。支持嵌套(Prefab 里含 Prefab)与变体(从基础 Prefab 派生出差异配置)。
  • 心智模型一句话:组件是零件,Prefab 是图纸,场景是装配现场。可复用的行为进组件与 Prefab,一次性的摆放留在场景。

2.3 包管理与工具生态

  • 官方能力按包模块化提供:用到才装,工程里「装了哪些包、为什么装」要能一句话说清,不用的定期清理。
  • 包有四个来源:官方注册表、资产商店、Git 地址、本地路径。第三方包进工程前评估五件事:体积、编译时间、许可证、维护状态、能否只取需要的部分。
  • 包污染是 Unity 工程最隐蔽的成本:一个大而全的资产包会同时抬高导入时间、编译时间与包体,还带来自己的目录结构、样例场景和旧依赖。纪律是先隔离试用,评审通过再进主工程。
  • 官方云服务(分析、云存档、多人中继等)按需接入,选型时就要评估替换成本。
  • 工具生态:IDE 集成(补全与调试)、编辑器脚本(把重复操作做成菜单命令)、单元测试与 Play 模式测试、性能分析工具(§5)。任何被手动做过三次的流程,都值得脚本化。

2.4 版本控制约定

Unity 工程与普通代码仓库的差异集中在两件事上:资产是二进制,而引用靠伴随文件。

  • 文本序列化:把资产序列化模式设为文本,场景与 Prefab 变成可读、可 diff、冲突可合并的文本文件。这是多人协作的前提,建仓第一天就切,别等出事了再补。
  • .meta 文件:每个资产与文件夹配一份 .meta,记录唯一标识与导入设置。三条规矩:随资产一起提交;只通过编辑器改名与移动(编辑器外的改名与移动会切断引用);不要手工编辑或删除。
  • Git LFS:纹理、音频、模型、视频、字体走大文件存储,仓库里只留指针。忽略清单从官方模板起步,Library/、Temp/、Logs/ 与构建产物一律不进库。
  • Smart Merge:官方提供的合并工具,在拉取与合并时对场景与 Prefab 的文本冲突做结构级合并。它只能处理语法层面的冲突,语义冲突(两人改了同一对象的不同属性)仍要人工判断。真正的解法是减少同名文件的并发编辑。
  • 协作纪律:按模块拆场景与 Prefab,避免多人同改一个大场景;提交信息写清改了什么行为与资产。

3. 核心工作流

3.1 编辑器里的日常循环

日常节奏:场景里拼装 → 进 Play 模式验证 → 退出后改脚本与资产 → 再进 Play 模式。三条纪律:

  • Play 模式里的修改不会保留:把 Play 模式当只读的观察窗口,记录问题,回到编辑态再改资产。
  • 复现问题用最小场景:从主场景剥出只含相关对象的测试场景,不要在完整关卡上调试。
  • 重复操作脚本化:批量改导入设置、批量生成资产、批量检查命名,都写成编辑器脚本一次执行。

3.2 场景与 Prefab 工作流

标准路径:白盒场景 → 识别重复对象 → 抽成 Prefab → 用嵌套与变体管理差异 → 场景只留摆放与少量有意覆盖。

  • 场景分层:环境(静态)、玩法对象(Prefab 实例)、系统(相机、管理器、光源)用根节点分开,谁都能看懂这棵树的形状。
  • 抽 Prefab 的时机:同一个对象第二次出现时。出现第三次还在复制粘贴,就是给自己埋债。
  • 实例覆盖要克制:在场景里改 Prefab 实例的属性会生成覆盖项,被覆盖的属性不再跟随基础 Prefab 的更新。允许少量有意覆盖,禁止随手乱改。
  • 变体处理同一原型的不同配置:不同数值的敌人、不同颜色的门这类差异用变体表达,不要复制一整棵子树。
  • 拆场景的信号:多人开始互相阻塞、单个场景加载变慢、一个场景塞进互不相关的模块。到这一步,按区域或玩法切场景,用异步加载拼接。

3.3 构建与多平台

Unity 的构建模型是「选目标平台、出对应产物」,三个平台族的差异:

平台族 产物形态 主要约束
桌面 可执行文件与数据目录 存储路径与图形接口的差异;约束最松
移动 商店分发的应用包 发热与内存最紧;必须真机测;iOS 要求 AOT 编译
Web 浏览器加载的网页产物 首次加载体积与时间是生命线;浏览器沙箱限制线程与能力;移动浏览器更弱
  • 脚本编译:目标平台不支持运行时编译(iOS、Web)时需要提前 AOT 编译,反射与动态生成代码的用法要早期验证,别等发版才暴露。
  • 构建配置化:每个目标的包名、图标、签名、场景清单、质量档位都是工程配置,建仓时固化成多套配置,别在发版当天手填。
  • 构建自动化:把构建做成命令行任务接进 CI,每次提交产出可玩版本(《技术实现手册》§6)。手动点菜单的构建只适合本机调试。
  • Web 与小游戏:Web 构建盯首包加载时间,资源切分与懒加载是常规手段;国内小游戏平台没有原生构建目标,经 Web 构建加适配方案转换,包体与性能门槛更严。
  • 多平台差异逐项打勾:输入方式、分辨率与安全区、平台生命周期(后台挂起与恢复)、权限弹窗、存储与云存档、字体与本地化(《全平台上架手册》的核对表可复用)。

4. 关键系统惯用法

4.1 脚本生命周期与执行顺序

生命周期回调是 Unity 编程的骨架。背下来不够,要理解两件事:谁在什么时候被调用,同一阶段里多个脚本的顺序不保证。

回调 时机 常见职责
Awake 对象被加载或实例化时一次(对象未激活则推迟) 抓取自身组件引用、初始化内部状态
OnEnable 每次被激活时 订阅事件、注册到管理器
Start 首次激活后、第一次帧更新之前一次 需要别的对象已就绪的装配逻辑
FixedUpdate 按固定时间步调用,一帧可能零次或多次 物理与力学相关逻辑
Update 每帧一次 输入采样、非物理逻辑、表现驱动
LateUpdate 每帧在全部 Update 之后 相机跟随、依赖其他对象本帧位置的逻辑
OnDisable / OnDestroy 失活与销毁时 退订事件、归还对象池、释放资源

执行顺序意识:

  • 同一阶段里,不同脚本之间默认没有稳定顺序。两个脚本在各自 Awake 里互相抓引用,谁先谁后全凭运气,现象是随机的空引用。
  • 收敛方式有两种:把耦合的初始化收进一个显式的入口(由一个脚本按序发起),或在编辑器里声明脚本执行顺序。项目越大越要靠前者,声明顺序只适合少量特例。
  • 跨阶段的坑:在 Awake 里读另一个对象 Start 阶段才准备好的数据;在 Update 里读物理结果,而物理其实在 FixedUpdate 里步进。
  • 把「谁依赖谁」画成一张有向图:无环、入口单一、顺序可预测。图乱掉的项目会在启动阶段随机崩溃,且难以复现。

4.2 ScriptableObject:数据资产

ScriptableObject 是序列化在工程里的数据对象,作用是把数据从场景对象里抽出来:数值表、配置、敌人档案、事件通道。它解决三件事:多处引用同一份数据、编辑器里可视化编辑、避免每个实例复制一份。

  • 数值与配置一律进数据资产:角色参数、关卡配置、经济表。散在场景与 Prefab 里的数值是维护灾难的源头。
  • 以数据资产为中介解耦:触发方与订阅方各自引用同一个数据资产(事件通道),互相不认识,模块间通知不用硬引用。
  • 运行时把它当只读:在编辑器里运行游戏时修改数据资产,改动会被写回资产本身,这是最常见的自坑方式;可变状态放进普通运行时对象。
  • 数据资产是普通资产:可 diff、可批量脚本处理、可走评审,数值改动因此有了流程与历史。

4.3 系统惯用法清单

对照《技术实现手册》§2 的跨引擎清单,Unity 语境下各系统的落点:

  • 输入:逻辑动作与物理按键分层,输入采样与固定物理步解耦,短按缓存按帧记账(《技术实现手册》§2.1)。
  • 对象池:子弹、特效、敌人这类高频对象一律池化,预热到峰值数量;引擎自带的池化方案优先于手写。
  • UI:数据与视图分离;把界面拆成多个画布单元,频繁变化的元素与静态元素分开,控制重建范围。
  • 存档:只存状态不存对象引用;带版本号与迁移逻辑;写入先临时文件再替换,防中断坏档。
  • 相机:跟随参数(前瞻、死区、缓动)与震屏限幅按《技术实现手册》§2.3 的清单执行,震屏必须可关闭。
  • 本地化:可见文本全部外置成键值;文本区域按多语言长度预留;字体回退链覆盖中日韩字符。

5. 性能与优化要点

方法论继承《技术实现手册》§3:先定预算、先测后改、真机大于编辑器。Unity 项目多发的热点集中在五处:

热点 症状 对策
每帧回调总量 帧率随对象数上升持续下跌 用少数管理器合并驱动、事件代替轮询、按需启用
托管内存分配 周期性卡顿(垃圾回收停顿) 消除热路径分配:字符串拼接、装箱、闭包、集合扩容;对象池
运行时查找 热点函数里全是查找调用 引用在初始化时抓一次并缓存;能用编辑器拖拽引用就不用代码查找
渲染提交 GPU 等待、CPU 忙于提交 合批与图集、减少材质切换与半透明面积;用帧调试器定位真凶
物理与动画 大量刚体或高密度骨骼时掉帧 分层碰撞过滤、简化碰撞体、降低物理频率、控制骨骼与蒙皮层数
  • 测量工具链:引擎 Profiler 看帧与内存,帧调试器看渲染提交,内存快照看资产驻留,平台性能工具做真机确认。编辑器数据常常失真,结论以真机为准。
  • 预算表:帧预算按目标帧率切分到逻辑、渲染、物理、UI;内存预算分平台;包体预算分渠道。超预算就报警,能进 CI 更好。
  • 移动端专项:发热降频(长时间运行后的帧率)、内存水位(被系统杀进程的风险)、包体积与下载转化;Web 专项:首包加载时间、浏览器内存上限、移动浏览器兼容矩阵。
  • 优化纪律:一次只改一个变量,改前改后记录同一场景同一路径的数据;没有测量不做优化。

6. 学习路线

按产物分四段,每段的里程碑都是可玩或可用的东西,不是看完的教程数:

  1. 引擎基本功(2-4 周量级):C# 基础、编辑器操作、组件模型。做三个小游戏覆盖:2D 移动与碰撞、UI 流程、存档读写;每个都发一次 Web 构建,顺手打通构建链路。
  2. 系统实现(1-2 个月量级):对照《技术实现手册》§2 逐项做最小实现(输入、对象池、相机、存档、UI、音频、本地化),每项一个小 demo。这一段的产出是能力库,之后项目直接取用。
  3. 工程化(贯穿始终):版本控制约定(§2.4)、构建流水线、性能预算与测量习惯(§5)、关键逻辑的测试。选一段自己写的代码,用 Profiler 找出三个热点并优化到数据可证明。
  4. 完整项目:进《制作管理手册》的流程,把工程基建拉满,走一次完整发布。

学习纪律:官方手册是概念与行为的权威依据,教程只用于入门与找手感;本页给出的判断随生态演化,遇到分歧以官方文档与你的 Profiler 为准。

7. 常见坑

  1. GetComponent 滥用:在 Update 里找组件、在循环里找组件,开销直接进帧预算。引用在初始化时抓一次并缓存,能用编辑器拖拽引用的就不用运行时查找。
  2. Update 全量开销:成百上千个对象各自持有每帧回调,逻辑各干各的。把同质对象交给管理器合并驱动,或用事件与状态变化驱动,别让每个对象每帧都醒着。
  3. 第三方包污染:为一个小功能导入整包资产,换来成吨的无用资源、编译时间与依赖冲突。先隔离试用、评审、只取需要的部分,导入后清理样例与未用资产。
  4. 每帧分配引发卡顿:字符串拼接、装箱、闭包捕获、循环里建集合都会制造垃圾回收压力。热路径上一个分配都不要有,池化与缓存是常规手段。
  5. 版本控制三连错:把 Library/ 提交进仓库、手工删除或改名 .meta、一直用二进制序列化。建仓当天就把 §2.4 的约定做完。
  6. 场景与 Prefab 的覆盖混乱:在场景里随手改 Prefab 实例的属性,改基础 Prefab 时行为不一致,谁改的都说不清。覆盖要有意识、有记录(§3.2)。
  7. 隐式依赖脚本执行顺序:靠「它应该先跑」来写初始化,现象是随机空引用。初始化收敛到显式入口或执行顺序设置(§4.1)。
  8. 只在编辑器里验证:编辑器帧率、输入与内存都与真机不同,移动端尤其。真机、目标机型、目标时长,三者缺一不算测过。
  9. 数据散落在场景里:数值直接写在组件上,改一个参数要满场景找。数据进数据资产(§4.2),场景只留摆放。

延伸阅读

  • 《技术实现手册》:架构选型、核心系统、性能方法论与工程基建,本文 §4、§5 的完整展开。
  • 《美术与音频手册》:资产规范、导入设置与表现反馈,涉及美术管线时对照。
  • 《制作管理手册》:原型到发布的阶段模型与范围控制,第 6 节项目段的入口。
  • 《小游戏开发手册》:各引擎导出小游戏的路线与包体约束,Web 与小游戏发布前必读。
  • Unity 官方手册与脚本参考:概念与行为的权威依据;本页判断随生态演化,以官方文档与你项目的 Profiler 为准。