34.性能优化-CPU-脚本-延迟函数
34.1 知识点
Invoke 和 InvokeRepeating
Unity 自带的 Invoke(延迟执行一次)和 InvokeRepeating(按间隔重复执行)用起来很简单,但会带来明显的性能和可维护性问题。
主要问题:
- 通过字符串(反射)查找并调用方法,性能消耗较高。
- 可读性差:字符串无法在 IDE 里直接跳转到对应方法,排查问题不方便。
- 无法传参:调用时不能传参数,只能通过成员变量间接传值。
- 控制不便:要停止时需调用 CancelInvoke,同样要传方法名字符串。
等等。因此更推荐用下面几种替代方案。
用法示例(仅作了解,不推荐在项目中滥用):
// 延迟 1 秒后执行一次 DoSomething
Invoke("DoSomething", 1f);
// 延迟 0.5 秒后开始,每隔 1 秒重复执行 DoSomething
InvokeRepeating("DoSomething", 0.5f, 1f);
// 停止所有通过字符串 "DoSomething" 调用的 Invoke/InvokeRepeating
CancelInvoke("DoSomething");
void DoSomething() { }
替代方案:利用协程替代
用协程实现「延迟执行」或「定时重复执行」:在协程里 yield return new WaitForSeconds(间隔),再执行逻辑;需要重复时用 while 包一层。
优点:支持传参(通过协程参数或闭包)、逻辑更集中、易管理、更灵活。
缺点:协程有额外开销(见上节课),需权衡。
// 延迟 1 秒后执行
StartCoroutine(DelayedCall(1f));
// 每隔 1 秒执行一次,共 5 次(示例)
StartCoroutine(RepeatingCall(1f, 5));
IEnumerator DelayedCall(float delay)
{
yield return new WaitForSeconds(delay);
DoSomething();
}
IEnumerator RepeatingCall(float interval, int count)
{
for (int i = 0; i < count; i++)
{
yield return new WaitForSeconds(interval);
DoSomething();
}
}
替代方案:UniTask
用 UniTask 的 API(如 UniTask.Delay)配合 async/await 实现延迟或定时逻辑。
优点:开销通常低于协程,结合 async/await 可读性更好、更易组合。
缺点:需要引入并学习 UniTask(如 Cysharp/UniTask)。
// 需引用 UniTask;延迟 1 秒后执行
await UniTask.Delay(TimeSpan.FromSeconds(1f));
DoSomething();
替代方案:自定义 Timer 管理器
自己实现或使用框架里的计时器模块(如 Unity 基础小框架中的计时器):统一注册、驱动、取消所有延迟/定时任务。
优点:统一管理、可控性强,可按项目需求自定义功能与优化方向(如分桶、对象池等)。
缺点:需要额外设计与实现(或接入现有框架)。
34.2 知识点代码
Lesson34_性能优化_CPU_脚本_延迟函数.cs
public class Lesson34_性能优化_CPU_脚本_延迟函数
{
#region 知识点一 Invoke和InvokeRepeating
/*
* Unity 自带 Invoke(延迟一次)、InvokeRepeating(定时重复)。
* 问题:通过字符串(反射)调用,性能与可维护性差;无法传参;停止需 CancelInvoke 传字符串。
* 更推荐用协程、UniTask 或自定义 Timer 管理器替代。
*/
#endregion
#region 知识点二 替代方案 —— 利用协程替代
/*
* 用协程 + WaitForSeconds 完成延迟/定时逻辑。
* 优点:支持传参、易管理、灵活。
* 缺点:协程有额外开销。
*/
#endregion
#region 知识点三 替代方案 —— UniTask
/*
* 用 UniTask.Delay 等 API 配合 async/await。
* 优点:开销较协程低,可读性更好。
* 缺点:需学习 UniTask。
*/
#endregion
#region 知识点四 替代方案 —— 自定义Timer管理器
/*
* 自定义计时管理器(如框架中的计时器模块),统一管理延迟/定时逻辑。
* 优点:可控、可自定义功能与优化。
* 缺点:需额外实现或接入框架。
*/
#endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com