You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中无需协程实现延迟执行?需依赖OnTriggerEnter2D参数

解决方案

首先要注意:你的原代码最后会立即销毁当前脚本所在的gameObject,如果直接用当前对象启动协程/Invoke,对象销毁后协程/Invoke会被终止,无法执行延迟销毁敌人的逻辑。下面是针对不同需求的可行方案:

方法1:用匿名协程+全局持久化对象(无需外部函数)

找一个全局的、不会被销毁的对象(比如标记了DontDestroyOnLoad的GameManager)来启动协程,这样即使当前对象被销毁,协程依然能执行:

void OnTriggerEnter2D(Collider2D other) 
{
    if (other.tag == "Enemy")
    {
        // 找到全局持久化对象(提前在场景中创建并命名)
        GameObject globalManager = GameObject.Find("GameManager");
        // 匿名协程直接捕获other参数
        globalManager.StartCoroutine(() => 
        {
            yield return new WaitForSeconds(2f); // 延迟2秒,可修改
            Destroy(other.gameObject);
        });
    }
    if (other.tag == "Button")
    {
        Debug.Log("button hit");
        door.MakeSpriteInvisible();
    }
    Destroy(gameObject); // 当前对象正常销毁
}

方法2:将延迟逻辑和自身销毁合并(用简单的外部协程,传参方便)

如果不介意写一个简短的外部协程函数,这种方式更清晰,还能控制自身销毁的时机:

void OnTriggerEnter2D(Collider2D other) 
{
    if (other.tag == "Enemy")
    {
        // 直接把other参数传给协程
        StartCoroutine(HandleEnemyDestroy(other));
    }
    else if (other.tag == "Button")
    {
        Debug.Log("button hit");
        door.MakeSpriteInvisible();
        Destroy(gameObject); // 触发按钮时立即销毁自身
    }
    // 触发敌人时不立即销毁,交给协程处理
}

// 外部协程直接接收other参数,逻辑清晰
IEnumerator HandleEnemyDestroy(Collider2D other)
{
    yield return new WaitForSeconds(2f);
    Destroy(other.gameObject); // 延迟销毁敌人
    Destroy(gameObject);       // 敌人销毁后再销毁自身
}

方法3:用Invoke+全局对象(简洁写法)

和协程思路类似,借助全局对象执行Invoke,避免当前对象销毁后任务终止:

void OnTriggerEnter2D(Collider2D other) 
{
    if (other.tag == "Enemy")
    {
        GameObject globalManager = GameObject.Find("GameManager");
        // Lambda捕获other参数,延迟执行销毁
        globalManager.Invoke(() => Destroy(other.gameObject), 2f);
    }
    if (other.tag == "Button")
    {
        Debug.Log("button hit");
        door.MakeSpriteInvisible();
    }
    Destroy(gameObject);
}

方法4:无协程/Invoke的时间戳方案

如果完全不想用Unity的协程/Invoke机制,可以通过记录待销毁对象和时间,在全局对象的Update中轮询:

  1. 在全局GameManager脚本中添加存储逻辑:
private List<(GameObject target, float destroyTime)> _pendingDestroys = new List<(GameObject, float)>();

public void AddDelayedDestroy(GameObject target, float delay)
{
    _pendingDestroys.Add((target, Time.time + delay));
}

void Update()
{
    // 倒序遍历避免删除元素时索引混乱
    for (int i = _pendingDestroys.Count - 1; i >= 0; i--)
    {
        var item = _pendingDestroys[i];
        if (Time.time >= item.destroyTime)
        {
            Destroy(item.target);
            _pendingDestroys.RemoveAt(i);
        }
    }
}
  1. 在你的触发脚本中调用:
void OnTriggerEnter2D(Collider2D other) 
{
    if (other.tag == "Enemy")
    {
        GameObject globalManager = GameObject.Find("GameManager");
        globalManager.GetComponent<GameManager>().AddDelayedDestroy(other.gameObject, 2f);
    }
    if (other.tag == "Button")
    {
        Debug.Log("button hit");
        door.MakeSpriteInvisible();
    }
    Destroy(gameObject);
}

内容的提问来源于stack exchange,提问作者lxjx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:30:14