【Unity】UniRx.Async에서 await 연골소 시 주의사항

13583 단어 UniRxUnity

2019/06/24 추기


라이브러리가 UniTask 로 분리되면 다음 동작이 수정됩니다.
연골소 await를 정확하게 연골소로 처리하는 쪽으로 통일한다.
다음은 과거의 일지로 남겨 둡니다.

입문


Unity 2018.3 이후와 Unity 2018.2, UniRx에서 코르크를 만들 때의 행동은 다르다.
  • Unity 2018.3 이후 UniRx.만약 Async를 사용하여 연골소의 await를 진행한다면, 연골소는 정상적으로 작용을 발휘할 수 없을 것이다
  • Unity 2018.2 이전에 UniRx를 사용하여 코르크를 하는 await의 부분은 문제없음
  • 아무 생각 없이 유니티 버전을 2018.2에서 2018.3으로 올리면 이 문제를 밟을 수 있다.

    무슨 현상이 일어났는가


    UniRx는 await 연골소의 기능을 가지고 있습니다.
    하지만 유니티 2018.2와 2018.3과는 다르다.
    정확히 말하면 UniRx.비헤이비어는 Async 활성화 여부에 따라 다릅니다.
    using System.Collections;
    using System.Threading.Tasks;
    using UniRx;
    using UnityEngine;
    using UniRx.Async; // 2018.3のときのみ有効化される
    
    public class CoroutineAwaitSample : MonoBehaviour
    {
        void Start()
        {
            Debug.Log(Application.unityVersion);
    
            AwaitCoroutineAsync();
        }
    
        private async Task AwaitCoroutineAsync()
        {
            Debug.Log($"Await前:{Time.frameCount}");
    
            await Coroutine();
    
            Debug.Log($"Await後:{Time.frameCount}");
        }
    
        private IEnumerator Coroutine()
        {
            Debug.Log($"====コルーチン開始:{Time.frameCount}");
    
            yield return new WaitForSeconds(1.0f);
    
            Debug.Log($"====コルーチン終了:{Time.frameCount}");
        }
    }
    
    

    2018.2 결과


    WaitForSeconds 정상적으로 운행하고 예상대로 플로피소를 운행한다.

    2018.3 결과


    WaitForSeconds 무시되어 코르크 단백질이 정상적으로 작동하지 않는다.

    왜?


    각 버전에서 호출Awaiter이 다르기 때문이다.
    IEnumerator를 await할 때
  • 2018.2에서 CoroutineAsyncBridgeGetAwaiter를 호출하여 IEnumerator를 연골소로 간주하여 await
  • 을 진행하다
  • 2018.3에서 호출EnumeratorAsyncExtensions, IEnumerator을 하나의 작은 데이터로 간주하여 await
  • 의 규격화 거리의 멱 함수.
    이 호출Awaiter이 다르기 때문에 이런 행위 차이가 나타난다.

    대책


    2018.3 이후 코르크단백질 await를 하려면 다음과 같은 방법으로 대책을 세울 수 있다.

    방법IENumerator를 코르크로 시작한 후 await

    StartCoroutine에서 코르크 단백질을 명확하게 가동한 후 await를 진행하는데 동작이 정확하다
    using System.Collections;
    using System.Threading.Tasks;
    using UniRx;
    using UnityEngine;
    using UniRx.Async; // 2018.3のときのみ有効化される
    
    public class CoroutineAwaitSample : MonoBehaviour
    {
        void Start()
        {
            Debug.Log(Application.unityVersion);
    
            AwaitCoroutineAsync();
        }
    
        private async Task AwaitCoroutineAsync()
        {
            Debug.Log($"Await前:{Time.frameCount}");
    
            // StartCoroutineでコルーチンを起動して、それをawaitする
            await StartCoroutine(Coroutine());
    
            Debug.Log($"Await後:{Time.frameCount}");
        }
    
        private IEnumerator Coroutine()
        {
            Debug.Log($"====コルーチン開始:{Time.frameCount}");
    
            yield return new WaitForSeconds(1.0f);
    
            Debug.Log($"====コルーチン終了:{Time.frameCount}");
        }
    }
    
    
    Observable.FromCoroutine 등도 문제없다.
    // コルーチンをObservableに変換してしまう
    await Observable.FromCoroutine(Coroutine);
    
    // Observable.FromCoroutineの省略記法
    await Coroutine().ToObservable();
    

    방법마이크로소프트 골소와 같은 방법을 사용하다


    UniRx는 MicroCoroutineyield return null만 허용하는 경량 코르크 기구를 설치했다.
    그것에 따라 yield return null의 코르크만 다시 쓰고 await는 그것의 방법을 사용했다.
    using System.Collections;
    using System.Threading.Tasks;
    using UniRx;
    using UnityEngine;
    using UniRx.Async; // 2018.3のときのみ有効化される
    
    public class CoroutineAwaitSample : MonoBehaviour
    {
        void Start()
        {
            Debug.Log(Application.unityVersion);
    
            AwaitCoroutineAsync();
        }
    
        private async Task AwaitCoroutineAsync()
        {
            Debug.Log($"Await前:{Time.frameCount}");
    
            await Coroutine();
    
            Debug.Log($"Await後:{Time.frameCount}");
        }
    
        private IEnumerator Coroutine()
        {
            Debug.Log($"====コルーチン開始:{Time.frameCount}");
    
            var startTime = Time.time;
            while (Time.time - startTime < 1.0f)
            {
                yield return null; // WaitForSecondsを使わない
            }
    
            Debug.Log($"====コルーチン終了:{Time.frameCount}");
        }
    }
    

    총결산


    2018.2에서 UniRx를 사용하는 경우 2018.3으로 업데이트하면 여기에 빠질 수 있습니다.
    코르크 단백질을 만드는await의 경우 특히 주의해야 한다.

    좋은 웹페이지 즐겨찾기