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

Unity基础学习(五)Mono中的重要内容(1)延时函数

目录

一、Mono中的延时函数Invoke

1. Invoke作用:延迟指定时间后执行一次函数。API:

2. InvokeRepeating作用:延迟后开始重复执行函数。API:

3. CancelInvoke作用:停止所有延时函数,或停止指定函数的延时执行。API:

4. IsInvoking作用:检查是否有延时函数正在运行。API:

二、 Update 循环 + 计时器实现延时

三、异步 async/await(需 .NET 4.x+)


一、Mono中的延时函数Invoke

1. Invoke
作用:延迟指定时间后执行一次函数。
API:

void Invoke(string methodName, float time);

methodName:要执行的函数名(字符串形式)。
time:延迟时间(秒)

示例:

void Start()
{// 3秒后执行 Shoot 函数Invoke("Shoot", 3f);
}void Shoot()
{Debug.Log("发射子弹!");
}

注意事项:
函数名必须为字符串且严格匹配。
无法直接传递参数,需通过成员变量间接实现。

2. InvokeRepeating
作用:延迟后开始重复执行函数。
API:

void InvokeRepeating(string methodName, float delay, float repeatRate);

methodName:函数名(字符串)。
delay:第一次执行的延迟时间。
repeatRate:后续每次执行的间隔时间。

void Start()
{// 延迟2秒后,每隔1秒生成一个敌人InvokeRepeating("SpawnEnemy", 2f, 1f);
}void SpawnEnemy()
{Debug.Log("敌人生成!");
}

注意:若需停止重复执行,需手动调用 CancelInvoke。 

3. CancelInvoke
作用:停止所有延时函数,或停止指定函数的延时执行。
API:

void CancelInvoke();              // 停止所有延时函数
void CancelInvoke(string methodName); // 停止指定函数名的延时

void Update()
{if (Input.GetKeyDown(KeyCode.Space)){// 停止所有延时函数CancelInvoke();// 或仅停止 SpawnEnemy 的延时CancelInvoke("SpawnEnemy");}
}

即使函数未在运行,调用 CancelInvoke 也不会报错。 

4. IsInvoking
作用:检查是否有延时函数正在运行。
API:

bool IsInvoking();              // 检查是否有任何延时函数在执行
bool IsInvoking(string methodName); // 检查指定函数是否在延时执行中

void Update()
{if (IsInvoking("SpawnEnemy")){Debug.Log("正在生成敌人...");}
}

关键特性与注意事项
对象状态影响:
脚本或对象失活(SetActive(false))时,延时函数仍会执行。
对象被销毁(Destroy)或脚本被移除时,延时函数自动终止。

函数要求:
必须为本脚本中声明的无参函数。
函数名需完全匹配(区分大小写)。

参数传递限制:
无法直接传参,可通过类成员变量间接实现:

private int _bulletType;void Start()
{_bulletType = 2;Invoke("Shoot", 1f);
}void Shoot()
{Debug.Log("发射类型为 " + _bulletType + " 的子弹");
}

二、 Update 循环 + 计时器实现延时

原理:在 Update 中通过累加 Time.deltaTime 手动控制计时器,触发目标函数。
优点:灵活性高,可中途修改延迟时间或逻辑。
缺点:需自行管理计时器,代码量稍多。

using UnityEngine;public class TimerExample : MonoBehaviour
{private float _delay = 2f;//延时时间private float _timer;//定时器private bool _hasTriggered;//是否处于延时间隔中void Update(){if (!_hasTriggered)//不处于延时间隔中{_timer += Time.deltaTime;//改变定时器 直到达到指定延时if (_timer >= _delay){DoSomething();_hasTriggered = true;}}}void DoSomething(){Debug.Log("2秒后执行!");}
}

例如实现一个可重复计时的定时器:

using UnityEngine;
using System;/// <summary>
/// 可重复触发的定时器(基于游戏时间)
/// </summary>
public class GameTimer
{// 定时器触发事件public event Action OnTimerTriggered;private float _interval;      // 触发间隔(秒)private float _nextTriggerTime; // 下次触发时间private bool _isActive;       // 定时器是否激活private bool _isRepeating;    // 是否重复触发/// <summary>/// 初始化定时器/// </summary>/// <param name="interval">触发间隔(秒)</param>/// <param name="isRepeating">是否重复</param>public GameTimer(float interval, bool isRepeating){_interval = interval;_isRepeating = isRepeating;}/// <summary>/// 启动/重启定时器/// </summary>public void Start(){_isActive = true;_nextTriggerTime = Time.time + _interval;}/// <summary>/// 停止定时器/// </summary>public void Stop(){_isActive = false;}/// <summary>/// 每帧更新定时器状态/// </summary>public void Update(){if (!_isActive || Time.time < _nextTriggerTime) return;// 触发事件OnTimerTriggered?.Invoke();if (_isRepeating){// 更新下次触发时间(避免误差累积)_nextTriggerTime = Time.time + _interval;}else{Stop();}}
}

 测试:

using UnityEngine;public class TimerExample : MonoBehaviour
{private GameTimer _gameTimer;private FrameTimer _frameTimer;void Start(){// 创建每5秒触发一次的重复定时器(精准时间)_gameTimer = new GameTimer(5f, true);_gameTimer.OnTimerTriggered += HandleGameTimer;_gameTimer.Start();// 创建每1秒触发一次的重复定时器(帧累积)_frameTimer = new FrameTimer(1f, true);_frameTimer.OnTimerTriggered += HandleFrameTimer;_frameTimer.Start();}void Update(){_gameTimer.Update();_frameTimer.Update();}void HandleGameTimer(){Debug.Log($"精准定时器触发,当前时间:{Time.time}");}void HandleFrameTimer(){Debug.Log($"帧累积定时器触发,运行时间:{Time.time}");}void OnDestroy(){_gameTimer.Stop();_frameTimer.Stop();}
}

三、异步 async/await(需 .NET 4.x+)

        这个是多线程的知识,主线程也是线程嘛,都可以直接作用。后面再详细介绍关于Task类的知识,这里简单了解即可。只需要知道 这样子也可以延时,后面我们学了协同,那个也可以延时。

async 修饰符:标记方法为异步方法,允许内部使用 await。
await 关键字:暂停当前异步方法的执行,直到其等待的任务完成,期间释放控制权给调用者。

原理:使用 C# 原生异步语法,通过 Task.Delay 实现延时。

优点:代码简洁,支持复杂异步逻辑。

缺点:需 Unity 2018+ 并启用 .NET 4.x 运行时版本。

环境配置

Player Settings -> Configuration -> Scripting Runtime Version -> .NET 4.x Project Settings -> Player -> Api Compatibility Level -> .NET 4.x 新版本可能不叫这个名字选.NET Framwork也是一样的

using UnityEngine;
using System.Threading.Tasks;public class AsyncAwaitExample : MonoBehaviour
{async void Start(){Debug.Log("开始等待...");await Task.Delay(2000); // 毫秒单位Debug.Log("2秒后执行!");// 注意:此处代码仍在主线程执行}
}

注意事项
若需操作 Unity 对象(如 GameObject),需在主线程执行,避免使用 Task.Run。
与协程不同,async/await 不依赖 Unity 的生命周期,但需处理对象销毁时的 Task 终止。 

http://www.xdnf.cn/news/569269.html

相关文章:

  • Model 是 Agent 的大脑(以camel为例)
  • 补充Depends 和 request: Request 依赖注入用法的注意事项
  • 【C++ Primer 学习札记】智能指针
  • 构建 PyMNN
  • Halcon窗口的基本操作
  • Elasticsearch生产环境性能调优指南
  • Spring Boot + +小程序, 快速开发零工市场小程序
  • 如何使用 Docker Compose 部署 Immich
  • 《棒球百科知识》世界棒球十强国家是如何发展·棒球1号位
  • WordPress Madara插件存在文件包含漏洞(CVE-2025-4524)
  • 实验分享|基于千眼狼sCMOS科学相机的流式细胞仪细胞核成像实验
  • XCOSnTh-fatfsShell
  • 腾讯位置服务地点搜索开发指南
  • [Min-Max Normalization] [Z-Score Normalization]
  • 使用vue2做一个生成二维码的案例【可当组件使用】
  • JC/T 2848-2024 玻璃纤维增强石膏(GRG)装饰制品检测
  • VS2022:使用命令行启动项目
  • 2023 睿抗机器人开发者大赛CAIP-编程技能赛-本科组(国赛) 解题报告 | 珂学家
  • vscode连接WSL卡住
  • js不同浏览器标签页、窗口或 iframe 之间可以相互通信
  • 虚拟机下的OpenWrt磁盘Overlay扩容
  • genicamtl_lmi_gocator_objectmodel3d
  • 掌握HTTPX:从基础到高并发工程实践
  • 自由开发者计划 001:创建一个用于查看 Jupyter Notebook 的谷歌浏览器插件
  • FPGA降低功耗研究
  • 【76. 最小覆盖子串】
  • 操作系统 第四章 -2
  • Docker安装MinIO对象存储中间件
  • 图片识别(TransFormerCNNMLP)
  • 分享一些多模态文档解析思路