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

Unity中已保存的Coroutine变量无法重启问题求助

问题描述

为AI单位实现了多个对应不同任务的协程,希望通过保存最近使用的协程实现「暂停」与「继续」功能,但遇到报错:执行MoveToResourceStart()时将MoveToResource()协程保存为lastCoroutine并启动;触发StopAlly()后停止该协程、重置导航路径并让单位看向玩家;触发ContinueAlly()尝试重启lastCoroutine时,系统报错:Coroutine 'lastCoroutine' couldn't be started!

精简代码如下:

Coroutine lastCoroutine = null;

protected void StopAlly(Transform player)
{
    if (lastCoroutine != null)
    { 
        StopCoroutine(lastCoroutine); 
        agent.ResetPath();
    }
    this.transform.LookAt(player.position);
}
protected void ContinueAlly()
{
   if (lastCoroutine != null) StartCoroutine("lastCoroutine");
} 

protected void MoveToResourceStart()
{
    if (lastCoroutine != null) StopCoroutine(lastCoroutine);
    lastCoroutine = StartCoroutine(MoveToResource());
}

protected IEnumerator MoveToResource()
{ 
    agent.SetDestination(resource.gameObject.transform.position);
    // 其他移动相关代码,运行正常
}
问题分析与解决方案

错误原因

  1. 协程对象无法重复启动:lastCoroutine是Coroutine类型的对象,一旦通过StopCoroutine停止后,该对象就会失效,无法再次通过StartCoroutine启动。
  2. 字符串启动方式错误:StartCoroutine("lastCoroutine")是通过方法名称字符串启动协程,但这里传入的是变量名而非协程方法的真实名称(正确应为"MoveToResource");即便传入正确名称,也只是启动一个全新的协程,无法恢复之前暂停的执行状态。

正确实现方式

Unity原生协程不支持直接暂停后恢复状态,因为协程本质是迭代器,停止后迭代器的执行状态会丢失,可通过以下两种思路实现需求:

思路1:用标记控制协程内部暂停/继续

不直接停止协程,而是在协程内部通过布尔标记控制执行流程,以此保留协程的中间状态:

Coroutine lastCoroutine = null;
bool isCoroutinePaused = false;

protected void StopAlly(Transform player)
{
    isCoroutinePaused = true;
    agent.ResetPath();
    this.transform.LookAt(player.position);
}

protected void ContinueAlly()
{
    isCoroutinePaused = false;
} 

protected void MoveToResourceStart()
{
    if (lastCoroutine != null)
    {
        StopCoroutine(lastCoroutine);
        isCoroutinePaused = false;
    }
    lastCoroutine = StartCoroutine(MoveToResource());
}

protected IEnumerator MoveToResource()
{ 
    agent.SetDestination(resource.gameObject.transform.position);
    
    while (!agent.hasReachedDestination)
    {
        // 暂停时循环等待,不执行后续逻辑
        while (isCoroutinePaused)
        {
            agent.isStopped = true; // 停止导航移动
            yield return null;
        }
        agent.isStopped = false; // 恢复导航移动
        // 其他移动相关逻辑
        yield return null;
    }
}

思路2:保存任务类型,重启对应协程

如果不需要恢复协程的中间状态,仅需重新执行同一个任务,可保存任务类型标识,重启时根据标识启动对应协程:

// 定义任务类型枚举
enum AllyTaskType { None, MoveToResource }
AllyTaskType lastTaskType = AllyTaskType.None;
Coroutine lastCoroutine = null;

protected void StopAlly(Transform player)
{
    if (lastCoroutine != null)
    { 
        StopCoroutine(lastCoroutine); 
        agent.ResetPath();
    }
    this.transform.LookAt(player.position);
}

protected void ContinueAlly()
{
    // 根据保存的任务类型启动对应协程
    switch(lastTaskType)
    {
        case AllyTaskType.MoveToResource:
            lastCoroutine = StartCoroutine(MoveToResource());
            break;
        // 可扩展其他任务类型的case
    }
} 

protected void MoveToResourceStart()
{
    if (lastCoroutine != null) StopCoroutine(lastCoroutine);
    lastTaskType = AllyTaskType.MoveToResource;
    lastCoroutine = StartCoroutine(MoveToResource());
}

protected IEnumerator MoveToResource()
{ 
    agent.SetDestination(resource.gameObject.transform.position);
    // 其他移动相关代码
    while (!agent.hasReachedDestination)
    {
        yield return null;
    }
    lastTaskType = AllyTaskType.None;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:20:33