从事件处理程序调用时,Unity Coroutine 未启动

Unity Coroutine is not starting when called from an event handler

我在尝试从事件处理程序的主体调用 StartCoroutine 时遇到问题。我希望在控制台上打印以下内容,而不是它只打印“之前”并且不会启动协程:

  1. 之前

  2. 里面

  3. 工作

  4. 之后

    private void Awake()
    {
        socket.OnMessage += (sender,e) => {
            Debug.Log("before");
            StartCoroutine(handleIncommingMessages(sender,e));
            Debug.Log("after");
        };
    }
    
    public IEnumerator handleIncommingMessages(object sender, MessageEventArgs e) {
    
        Debug.Log("inside");
        yield return new WaitForSeconds(3f);
        Debug.Log("working");
    
    }
    

事件调用完成后协程被丢弃可能存在问题。我不知道如何修复它 - 但如果您使用的是较新版本的 Unity,则可以改用任务:

private void Awake()
{
    // We add async so that we can use the `await` call.
    socket.OnMessage += async (sender,e) => { 
        Debug.Log("before");
        
        // Force it to await when the incoming message as not to close the thread
        await handleIncommingMessages(sender, e);
        
        Debug.Log("after");
    };
}

public async Task handleIncommingMessages(object sender, MessageEventArgs e) {

    Debug.Log("inside");
    await Task.Delay(1000);
    Debug.Log("working");

}

如果这不起作用,请尝试: public async void handleIncommingMessages 而不是 Task

这个协程只能在主线程中运行。你必须将你要执行的协程的方法注入到主线程中。

通常当您尝试在另一个线程中 运行 它时,您会收到此错误: UnityException: IsObjectMonoBehaviour 只能从主线程调用。

我通过定义 public 列表并使用更新方法解决了这个问题。

List<Action> threadPumpList = new List<Action>();

private void Update()
{
    while (threadPumpList.Count > 0)
    {
        threadPumpList[0].Invoke();
        threadPumpList.RemoveAt(0);
    }
}

public void WriteTestMessage()
{
    Debug.Log("Hello World.")
}

public void Test()
{
    threadPumpList.Add(() => WriteTestMessage());
}

你可以这样用。

List<IEnumerator> threadPumpList = new List<IEnumerator>();

private void Update()
{
    while (threadPumpList.Count > 0)
    {
        StartCoroutine(threadPumpList[0]);
        threadPumpList.RemoveAt(0);
    }
}

private void Awake()
{
    //socket.OnMessage += (sender,e) =>
    new Thread(() => //You should use socket right here.
      {
        Debug.Log("before");
        threadPumpList.Add(handleIncommingMessages(null, ""));
        Debug.Log("after");
    }).Start();
}


public IEnumerator handleIncommingMessages(object sender, string e) //I changed parameters for testing.
{

    Debug.Log("inside");
    yield return new WaitForSeconds(3f);
    Debug.Log("working");

}

当我测试它时,输出是这样的:

-之前 -后 -里面 (等待 3 秒) -工作