Unity中销毁和禁用对Invoke和协程的调用的影响

在 Unity 开发中,我们经常需要在游戏对象的生命周期中进行一些异步操作,比如使用 Invoke 延时调用方法,或启动协程来处理复杂的逻辑。然而,当游戏对象被销毁或禁用时,这些操作会如何表现呢?

在这篇博客中,我将分享三种常见情况:延迟调用之前销毁游戏对象 和 延迟调用之前禁用游戏对象 和 延迟调用之前禁用当前脚本,并深入探讨它们对 Invoke 和协程执行的影响,以及如何避免由此引发的潜在问题。通过这些案例分析,你将更清晰地理解 Unity 中对象的生命周期管理,帮助你在项目中更有效地控制异步操作的执行。

情况一:延迟调用之前,游戏对象被Destroy

在此段代码中,游戏物体有两个延迟调用函数,一个是通过Invoke,另一个是通过协程,它们都是10秒后被调用,但是在5秒后物体就会被Destroy。

    void Start()
    {
        Invoke(nameof(invokeFunction),10f);
        StartCoroutine(coroutineFunction(10f));
        Destroy(gameObject, 5f);

    }
    public void invokeFunction()
    {
        print("invoke函数执行了");
    }
    public IEnumerator coroutineFunction(float time)
    {
        yield return new WaitForSeconds(time);
        print("coroutine函数执行了");
    }

结果:Invoke函数和协程都不会执行。

情况二:延迟调用之前,游戏对象被禁用

此段代码与上面那种情况区别就是5秒后不再Destroy,而是使物体失活。

    void Start()
    {
        Invoke(nameof(invokeFunction),10f);
        StartCoroutine(coroutineFunction(10f));
        StartCoroutine(EnableActive(5f));

    }
    public void invokeFunction()
    {
        print("invoke函数执行了");
    }
    public IEnumerator coroutineFunction(float time)
    {
        yield return new WaitForSeconds(time);
        print("coroutine函数执行了");
    }
    public IEnumerator EnableActive(float time)
    {
        yield return new WaitForSeconds(time);
        gameObject.SetActive(false);
    }

结果:Invoke函数会执行,协程不执行。

情况三:延迟调用之前,脚本被禁用。

测试代码如下。

    void Start()
    {
        Invoke(nameof(invokeFunction),10f);
        StartCoroutine(coroutineFunction(10f));
        StartCoroutine(EnableScriptActive(5f));


    }
    public void invokeFunction()
    {
        print("invoke函数执行了");
    }
    public IEnumerator coroutineFunction(float time)
    {
        yield return new WaitForSeconds(time);
        print("coroutine函数执行了");
    }
    public IEnumerator EnableScriptActive(float time)
    {
        yield return new WaitForSeconds(time);
        this.enabled = false;
    }

结果:Invoke函数和协程都会执行。

Unity 内部处理逻辑:

1. 游戏对象销毁(Destroy(gameObject)

Destroy(gameObject) 被调用时,Unity 会在指定的时间之后完全销毁该游戏对象,以及它上面所有的组件,包括脚本。

  • Invoke:游戏对象销毁后,所有由 Invoke 创建的函数调用都会被终止,因此 Invoke 的回调不会执行。
  • 协程:协程同样会在对象销毁时终止,所有关联的协程将停止,不会继续执行或恢复。

2. 游戏对象禁用(SetActive(false)

当你调用 SetActive(false) 禁用游戏对象时,该对象在场景中仍然存在,但它以及所有子对象都将被禁用(即非活动状态)。

  • Invoke:Invoke 方法是通过 Unity 的时间系统调度的,它不依赖于特定的 GameObject 或组件的激活状态。即使 GameObject 被禁用,Invoke 也会继续执行。

  • 协程:当 GameObject 被禁用时,所有附加在该 GameObject 上的脚本的协程都会被停止。因此,coroutineFunction 不会继续执行,也就不会打印 "coroutine函数执行了"。

3. 脚本禁用(this.enabled = false

this.enabled = false 禁用某个脚本时,游戏对象仍然是激活状态,但该脚本的执行会被部分暂停。具体来说:

  • Invoke:同样,Invoke 方法不受脚本启用状态的影响,它仍然会执行。

  • 协程:当脚本被禁用时,已经启动的协程会继续运行直到完成。这是因为协程一旦启动,就成为了独立的执行单元,不再直接依赖于脚本的启用状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值