第 2 章 · 脚本值班表:事件函数与 C# 功底 本章要回答的三个问题:为什么同一个脚本里写的代码,有时一瞬间全跑完、有时每帧跑一次、有时还要等物理忙完才轮到它?协程和普通函数都是"执行一段逻辑",凭什么协程能暂停?物体之间互发消息,用直接调用还是用事件?这三个问题的答案,就是本章的排班表。 为什么会有这一章 第 1 章结束时,值班室还只是一堆不会动的工位。让它们动起来的东西是脚本,但脚本最常见的死法不是"不会写",而是"写对了逻辑、放错了时点":把初始化放在 Update 里导致每帧申请内存,把依赖其他对象的取值放在 Awake 里拿到一串空引用,在 FixedUpdate 里做每帧 UI 刷新把物理步骤拖到超时。这些事故的共同根源,是不清楚引擎在什么时点调用你的哪段代码。
本章要回答的三个问题:为什么同一个脚本里写的代码,有时一瞬间全跑完、有时每帧跑一次、有时还要等物理忙完才轮到它?协程和普通函数都是"执行一段逻辑",凭什么协程能暂停?物体之间互发消息,用直接调用还是用事件?这三个问题的答案,就是本章的排班表。
第 1 章结束时,值班室还只是一堆不会动的工位。让它们动起来的东西是脚本,但脚本最常见的死法不是"不会写",而是"写对了逻辑、放错了时点":把初始化放在 Update 里导致每帧申请内存,把依赖其他对象的取值放在 Awake 里拿到一串空引用,在 FixedUpdate 里做每帧 UI 刷新把物理步骤拖到超时。这些事故的共同根源,是不清楚引擎在什么时点调用你的哪段代码。
换值班室的说法:MonoBehaviour 上的那些特殊函数(Awake、Start、Update、FixedUpdate、LateUpdate、OnDestroy……)是一张引擎定死的排班表,你的代码只是往对应的班次里填内容。填错班次,逻辑再对也是事故。本章前两节把排班表与 C# 岗位说明书讲透,后两节补上两件跨班次的通信工具——协程(可暂停的长任务)与委托事件(值班室对讲机)。
| 节 | 回答的问题 | 关键产出 |
|---|---|---|
| 2.1 事件函数排班表 | 引擎按什么顺序调用我的代码 | 一张完整的一帧时序图与放置原则 |
| 2.2 C# 面向对象 | MonoBehaviour 底下是什么类结构 | 会写继承、接口与可复用的基类 |
| 2.3 协程 | 怎么写"做一半歇一下"的任务 | 三个可复用的协程模板 |
| 2.4 委托与事件 | 模块间怎么发通知不互相拉扯 | 一套事件广播的落地写法 |
一句金句:写 Unity 脚本,先问"这段代码几点上班"——逻辑对了、班次错了,照样翻车。

问:Update 里能写物理吗?偶尔好像也没事。
能写,但它在赌概率。FixedUpdate 的节拍与 Update 不同步,偶尔"没事"是因为物理误差恰好没被观察到;帧率一波动,穿墙、抖动、受力不一致全都会冒出来。物理账单别赌,纪律写进 2.1 节的排班表里了。
问:协程和 Update 里的计时器变量,该用哪个?
看任务形态。一段"有先后顺序、带等待"的流程(开场演出、延迟刷怪)用协程,写成流水账最清晰;一个"每帧都可能变化的状态"(蓄力进度、无敌帧倒计时)用 Update 加字段维护。强行互换都会写出别扭代码。
问:事件订阅了没退订,当时看不出问题,怎么破?
这正是事件的危险之处:泄漏是慢性病。守一条铁律——OnEnable 里 += 的,OnDisable 里必须 -=,一行都不能少。审查别人的代码时,看到 += 就搜对应的 -=,搜不到就是隐患。静态事件尤其如此,它挂着的死对象会活到整个游戏结束。
本章结束时,值班员已经能在正确的时间做正确的事。第 3 章给他们派活:输入岗把玩家按键变成意图,物理岗让角色真的跳起来撞上墙。2.4 节的事件广播会在第 4 章 UI、第 5 章对象池里反复出现,属于全书复用率最高的工具。