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

Unity协程yield return后代码不执行,敌人无法重生问题

问题原因

你当前的代码中,协程是通过敌人GameObject上的脚本启动的:StartCoroutine(resScript.Respawn(...))。当敌人被SetActive(false)后,挂载该脚本的GameObject处于禁用状态,Unity会暂停所有由该对象启动的协程,导致yield return WaitForSeconds(5)之后的代码永远不会执行。

解决方案

方案1:让GameManager启动协程(推荐)

修改重生脚本,新增一个公开方法,内部由GameManager的MonoBehaviour启动协程,确保协程的生命周期不受敌人对象状态影响:

public class RespawnScript : MonoBehaviour
{
    // 对外公开的启动重生方法
    public void TriggerRespawn(float cooldown, GameObject enemy, Vector2 spawnPos)
    {
        // 用GameManager自身的MonoBehaviour启动协程
        StartCoroutine(RespawnCoroutine(cooldown, enemy, spawnPos));
    }

    // 将原Respawn改为私有协程方法
    private IEnumerator RespawnCoroutine(float cooldown, GameObject enemy, Vector2 spawnPos) 
    {
        enemy.SetActive(false);
        yield return new WaitForSeconds(cooldown); // 用传入的cooldown而非固定5秒更灵活
        print("got past yield return");
        enemy.SetActive(true);
        enemy.transform.position = spawnPos; 
    }
}

然后修改敌人死亡脚本的Death方法,调用GameManager的启动方法而非自己启动协程:

public void Death()
{
    playerStats.onXpGathered(stats.xpReward);
    if(canRespawn)
    {
        health = stats.maxHealth;
        // 调用GameManager的重生触发方法
        resScript.TriggerRespawn(respawnTime, gameObject, spawnPos);
    }
    else
    {
        Destroy(gameObject);
    }        
}

方案2:用Update计时器实现

如果你想继续使用Time.deltaTime的方式,可在GameManager的重生脚本中维护一个重生队列,通过Update帧更新计时:

public class RespawnScript : MonoBehaviour
{
    // 存储待重生的敌人数据
    private List<RespawnEntry> _respawnQueue = new List<RespawnEntry>();

    // 定义重生数据结构
    private struct RespawnEntry
    {
        public GameObject enemy;
        public Vector2 spawnPos;
        public float remainingCooldown;
    }

    // 对外公开的入队方法
    public void AddToRespawnQueue(float cooldown, GameObject enemy, Vector2 spawnPos)
    {
        enemy.SetActive(false);
        _respawnQueue.Add(new RespawnEntry
        {
            enemy = enemy,
            spawnPos = spawnPos,
            remainingCooldown = cooldown
        });
    }

    void Update()
    {
        // 倒序遍历避免删除元素时索引混乱
        for (int i = _respawnQueue.Count - 1; i >= 0; i--)
        {
            var entry = _respawnQueue[i];
            entry.remainingCooldown -= Time.deltaTime;

            if (entry.remainingCooldown <= 0)
            {
                // 执行重生逻辑
                entry.enemy.SetActive(true);
                entry.enemy.transform.position = entry.spawnPos;
                _respawnQueue.RemoveAt(i);
            }
            else
            {
                // 更新队列中的剩余时间
                _respawnQueue[i] = entry;
            }
        }
    }
}

敌人死亡脚本的Death方法修改为:

public void Death()
{
    playerStats.onXpGathered(stats.xpReward);
    if(canRespawn)
    {
        health = stats.maxHealth;
        resScript.AddToRespawnQueue(respawnTime, gameObject, spawnPos);
    }
    else
    {
        Destroy(gameObject);
    }        
}
额外检查点
  1. 确保GameManager GameObject始终处于激活状态,未被禁用或销毁
  2. 确认敌人对象仅被SetActive(false)而非Destroy(你的代码中canRespawn分支确实没有销毁敌人,这点没问题)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 15:05:01