Coding Memo

Coroutine 실행 에러 본문

Unity

Coroutine 실행 에러

minttea25 2023. 12. 22. 18:17

Summary

 

Coroutine은 반드시 Unity 메인 스레드에서만 실행되어야 한다. (다른 스레드에서 StartCoroutine을 호출해도 소용없다!)

 

외부 스레드에서 Unity 오브젝트 접근을 막아 놓은 것과 동일한 맥락으로 생각하면 될 것 같다.


내가 겪었던 문제는 다음과 같다.

 

Situation

Client가 Server에 연결이 되고 연결이 되었을 때의 callback으로 서버에 ping 패킷을 보내는 Coroutine을 호출하고 있었다. tcp 연결은 내가 간단하게 만든 라이브러리에서 실행이 된다.

 

코드를 간단하게 나타내면 다음과 같다.

StartCoroutineEx는 static이고 MonoBehaviour를 상속하고 있는 CoroutineManager에 있는 static함수로, IEnumerator 타입을 하나 파라미터로 받고 그 값을 코루틴으로 실행시키는 함수이다.

// called when the client is connected to server. (async)
void OnConnected() 
{
	...
    _ = CoroutineManager.StartCoroutineEx(SendPing());
}

IEnumerator SendPing()
{
	...
}

 

 

Problem

StartCoroutineEx() 함수가 (정확히는 이 함수 내부에 있는 StartCoroutine() 함수가) 어떠한 값도 return하지 않았다. 이후 코드가 실행이 되지 않았다는 뜻이다. Unity Console에서도 별다른 에러가 나타나지않았다.

 

Solve

OnConnected() 함수가 Unity 메인 스레드에서 호출이 되고 있는 함수가 아니었다. 따라서 Unity 메인 스레드에서만 호출 될 수 있는 Coroutine이 정상적으로 실행되지 않았던 것이었다.

 

왜 오류가 나타나지 않았을까? 

 

내 생각이긴한데, 현재 OnConnected는 IOCP에서 처리되어서 실행되는 함수로 별도의 스레드에서 처리된다. 이쪽에서 코루틴이 실행이 되었을 때 예외를 던지거나 오류를 표시하는 작업이 포함이되어 있지 않기 때문이라고 추측한다. 

이를 확인하기 위해 IOCP 스레드가 아닌 내가 직접 스레드를 생성하고 코루틴을 실행시켜보았더니 제대로된 에러가 나타난것을 확인할 수 있었다.

public class TestScript
{
    public void DoTask()
    {
    	// 코루틴을 별도의 스레드에서 실행
        Thread t = new Thread(() => { CoroutineManager.StartCoroutineEx(Func()); });
        t.Start();
    }


    IEnumerator Func()
    {
        yield return null;

        while (true)
        {
            Debug.Log("Func");
            yield return new WaitForSeconds(3);
        }
    }
}

 

 

public class TestManager : MonoBehaviour
{
    TestScript t = new();

    void Start()
    {
        t.DoTask();
    }
}

 

'Unity' 카테고리의 다른 글

UnityWebRequest 코드  (0) 2024.07.16
Unity에서 UnityWebRequest 사용 시, 에러 (Curl error60) (localhost, loopback)  (2) 2024.07.16
[AddressableAssets] SBP ErrorError  (0) 2023.09.06
SerializedObject  (1) 2023.05.12
Unity Tip - UI 최적화 1  (0) 2023.05.08