当前位置: 首页 > news >正文

Unity中的延迟调用方法详解

目录

1. Invoke系列方法

InvokeRepeating方法(定时重复调用)

Invoke方法(单次延迟调用)

CancelInvoke方法(取消调用)

2. 协程(Coroutine)方法

基础协程实现

周期性协程实现

3. 方法对比与选择指南

详细对比表格

选择建议

4. 协程管理高级技巧

协程的生命周期控制

协程的实用模式

5. 性能优化建议

6.补充


1. Invoke系列方法

InvokeRepeating方法(定时重复调用)

InvokeRepeating是Unity提供的一个非常实用的方法,它允许你在特定时间间隔重复调用某个方法。这个方法特别适合需要周期性执行的任务,如敌人AI的决策、游戏数值的更新等。

完整示例:

using UnityEngine;public class TimerExample : MonoBehaviour
{void Start(){// 参数说明:// 1. 方法名(字符串形式)// 2. 首次调用延迟时间(2秒)// 3. 重复调用间隔(1秒)InvokeRepeating("UpdateGameState", 2f, 1f);}void UpdateGameState(){// 这里可以执行游戏状态更新逻辑Debug.Log("Game state updated at: " + Time.time);// 实际应用中可能包含:// - 更新NPC行为// - 刷新资源再生// - 检查任务完成状态}
}

Invoke方法(单次延迟调用)

当只需要延迟执行一次方法时,可以使用Invoke方法。这在游戏开发中常用于实现技能冷却、延迟特效等场景。

扩展示例:

using UnityEngine;public class SkillSystem : MonoBehaviour
{public GameObject explosionEffect;void Start(){// 3秒后释放技能Invoke("CastFireball", 3f);}void CastFireball(){// 创建爆炸特效Instantiate(explosionEffect, transform.position, Quaternion.identity);// 伤害计算// DealDamage(50);Debug.Log("Fireball casted at: " + Time.time);}
}

CancelInvoke方法(取消调用)

CancelInvoke用于取消通过InvokeInvokeRepeating设置的调用计划。这在角色死亡、游戏暂停等需要中断定时逻辑的场景中非常有用。

增强示例:

using UnityEngine;public class EnemyAI : MonoBehaviour
{void Start(){// 每2秒执行一次AI决策InvokeRepeating("MakeDecision", 0f, 2f);}void MakeDecision(){if(GetComponent<Health>().IsDead){CancelInvoke("MakeDecision");return;}// AI决策逻辑Debug.Log("AI making decision at: " + Time.time);}void OnDestroy(){// 确保对象销毁时取消所有调用CancelInvoke();}
}

2. 协程(Coroutine)方法

基础协程实现

协程提供了更灵活的时间控制方式,特别适合需要复杂时序控制的场景。

详细示例:

using UnityEngine;
using System.Collections;public class CoroutineExample : MonoBehaviour
{IEnumerator Start(){Debug.Log("Coroutine started at: " + Time.time);// 等待2秒yield return new WaitForSeconds(2f);// 执行延迟方法ShowMessage();// 可以继续添加更多延迟逻辑yield return new WaitForSeconds(1f);Debug.Log("Additional action after 1 more second");}void ShowMessage(){Debug.Log("Message shown after delay at: " + Time.time);}
}

周期性协程实现

通过while循环和yield return结合,可以实现精确的周期性调用。

增强实现:

using UnityEngine;
using System.Collections;public class PeriodicUpdater : MonoBehaviour
{[SerializeField] private float updateInterval = 0.5f;private bool isRunning = true;IEnumerator Start(){while(isRunning){// 执行更新逻辑UpdateGameLogic();// 等待指定间隔yield return new WaitForSeconds(updateInterval);}}void UpdateGameLogic(){// 这里可以放置需要周期性执行的逻辑Debug.Log("Periodic update at: " + Time.time);// 例如:// - 更新UI显示// - 检查游戏条件// - 自动保存游戏}void OnDisable(){// 当组件被禁用时停止协程isRunning = false;}
}

3. 方法对比与选择指南

详细对比表格

特性Invoke/InvokeRepeating协程(Coroutine)
语法复杂度简单中等
时间精度依赖帧率高精度
代码可读性一般优秀
复杂逻辑支持有限优秀
多步骤延迟不支持支持
条件等待不支持支持(yield return waitUntil)
内存开销较低略高

选择建议

  1. 简单延迟/周期任务:优先考虑Invoke系列

    • 技能冷却
    • 简单计时器
    • 一次性延迟效果
  2. 复杂时序控制:使用协程

    • 需要等待多个条件
    • 包含多个步骤的动画序列
    • 资源加载流程
    • 复杂的AI行为树
  3. 高精度定时:使用协程

    • 音乐节奏游戏
    • 精确的物理模拟
    • 网络同步

4. 协程管理高级技巧

协程的生命周期控制

using UnityEngine;
using System.Collections;public class CoroutineManager : MonoBehaviour
{private Coroutine activeCoroutine;void Start(){// 存储协程引用以便后续管理activeCoroutine = StartCoroutine(ComplexRoutine());}IEnumerator ComplexRoutine(){Debug.Log("Starting complex routine");yield return new WaitForSeconds(1f);// 分段执行yield return StartCoroutine(SubRoutine1());yield return StartCoroutine(SubRoutine2());Debug.Log("Complex routine completed");}IEnumerator SubRoutine1(){yield return new WaitForSeconds(0.5f);Debug.Log("Sub-routine 1 executed");}IEnumerator SubRoutine2(){yield return new WaitForSeconds(0.3f);Debug.Log("Sub-routine 2 executed");}void OnDisable(){// 安全停止协程if(activeCoroutine != null){StopCoroutine(activeCoroutine);}}
}

协程的实用模式

  1. 超时模式
IEnumerator LoadWithTimeout(float timeout)
{AsyncOperation operation = SceneManager.LoadSceneAsync("MainScene");float startTime = Time.time;while(!operation.isDone){if(Time.time - startTime > timeout){Debug.LogError("Loading timed out!");yield break; // 提前退出协程}yield return null;}Debug.Log("Scene loaded successfully");
}

  1. 并行协程
IEnumerator RunParallelCoroutines()
{// 同时启动多个协程Coroutine coroutineA = StartCoroutine(TaskA());Coroutine coroutineB = StartCoroutine(TaskB());// 等待所有协程完成yield return coroutineA;yield return coroutineB;Debug.Log("All parallel tasks completed");
}

  1. 条件等待
IEnumerator WaitForCondition()
{// 等待玩家按下空格键yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));// 等待敌人数量少于3yield return new WaitWhile(() => GameObject.FindGameObjectsWithTag("Enemy").Length >= 3);Debug.Log("Conditions met, proceeding...");
}

5. 性能优化建议

  1. 避免频繁创建/销毁协程:复用现有的协程
  2. 谨慎使用无限循环:确保有退出条件
  3. 减少字符串方法名调用:Invoke使用字符串方法名会有反射开销
  4. 协程分组管理:对于大量协程,考虑使用专用管理器
  5. 注意垃圾回收:yield return新建对象会产生GC

通过合理选择和组合这些延迟调用方法,可以构建出既高效又易于维护的游戏逻辑系统。
 

6.补充

这里有两个序列化的UnityEvent,可能看代码不是很直观,直接上图。

      

是不是感觉很眼熟。对就是,像我们经常看到的Button下边的OnClick其实就是这种东西。

我们为这个东西挂上我们自己的测试脚本。

但是这时候我们想要调用测试脚本的方法了,这时候就用到了Invoke。

这里会自动调用UnityEvent下的脚本的指定方法。

http://www.lryc.cn/news/622080.html

相关文章:

  • [微服务]ELK Stack安装与配置全指南
  • STM32在使用DMA发送和接收时的模式区别
  • 机器学习之 KNN 算法学习总结
  • YTHDC1介导MAFF核输出减轻肝细胞缺血再灌注氧化应激损伤
  • exec函数族、线程
  • 新手入门Makefile:FPGA项目实战教程(二)
  • 【计算机视觉与深度学习实战】02基于形态学的权重自适应图像去噪系统
  • 大模型 + 垂直场景:搜索 / 推荐 / 营销 / 客服领域开发有哪些新玩法?
  • 短剧小程序系统开发:打造个性化娱乐新体验
  • Apache 如何支持SHTML(SSI)的配置方法
  • 告别手动优化!React Compiler 自动记忆化技术深度解析
  • Docker部署Spring Cloud微服务实战
  • vue一个超简单的菜单栏伸缩示例
  • 剧本杀小程序系统开发:重构推理娱乐生态
  • C语言第八章指针五
  • linux服务器查看某个服务启动,运行的时间
  • Chrome插件开发
  • 最长递增子序列-dp问题+二分优化
  • 智能巡检技术浅析
  • 最新chrome浏览器elasticsearch-head无法安装使用问题
  • 牛市暴跌后什么时候进入好
  • C++ 调试报错 常量中有换行符
  • NAS播放器的新星,一站式全平台媒体库管理工具『Cinemore』体验
  • 高通vendor app访问文件
  • 前端css学习笔记6:盒子模型
  • IP生意的天花板更高了吗?
  • 多路混音声音播放芯片型号推荐
  • Microsoft Visual Studio常用快捷键和Windows系统常用快捷键的整理
  • 深入解析五大通信协议:TCP、UDP、HTTP_HTTPS、WebSocket与GRPC
  • 【Leetcode hot 100】53.最大子数组和