Unity3dAsyncAwaitUtil icon indicating copy to clipboard operation
Unity3dAsyncAwaitUtil copied to clipboard

Cannot use for Editor unit testing, as SyncContextUtil.Install is not called except at runtime

Open jokigenki opened this issue 6 years ago • 7 comments

I hacked this by making SyncContextUtil.Install public and calling it in my tests SetUp method, but I don't know if there's a better way?

jokigenki avatar Sep 06 '18 05:09 jokigenki

We should probably change it to use the [InitializeOnLoad] instead of [RuntimeInitializeOnLoad]. But I'd have to test it to be sure that works correctly

svermeulen avatar Sep 07 '18 13:09 svermeulen

Since I'm not sure that runs before awake. But we could use both attributes in that case too

svermeulen avatar Sep 07 '18 13:09 svermeulen

Unity also doesn't support executing the async in the editor as well, you'll also need a pump.

See https://forum.unity.com/threads/async-await-in-editor-script.481276/

StephenHodgson avatar Sep 07 '18 14:09 StephenHodgson

Here's an modified version of @svermeulen's project that I included in another project. I've been meaning to open pull requests to add this stuff back but I've been pretty busy.

#if UNITY_EDITOR
        private static System.Reflection.MethodInfo executionMethod;

        /// <summary>
        /// HACK: makes Unity Editor execute continuations in edit mode.
        /// </summary>
        private static void ExecuteContinuations()
        {
            if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return;
            }

            var context = SynchronizationContext.Current;

            if (executionMethod == null)
            {
                executionMethod = context.GetType().GetMethod("Exec", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            }

            executionMethod?.Invoke(context, null);
        }

        [UnityEditor.InitializeOnLoadMethod]
#endif
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
        private static void Initialize()
        {
#if UNITY_EDITOR
            UnityEditor.EditorApplication.update += ExecuteContinuations;
#endif
            UnitySynchronizationContext = SynchronizationContext.Current;
            UnityThreadId = Thread.CurrentThread.ManagedThreadId;
        }

StephenHodgson avatar Sep 07 '18 14:09 StephenHodgson

@StephenHodgson Thank you for this -- I was unable to find documentation of this after quite a bit of searching Unity's forums. Never occurred to me to just build my project and see that my async worked, and of course it did. The code you shared makes the editor work, too.

Can this technique also be used to use the thread pool to run non-UI async tasks that don't need to access the Unity API?

Does anyone know if there is official Unity documentation on this anywhere?

anticrisis avatar Sep 21 '18 18:09 anticrisis

Hi,

I've been experimenting with this a bit and async works as expected. However, I found it was of limited use since you can't touch any part of the Unity API, and most of the stuff I wanted to do ended up needing to go through the API. Depending on what you want it for, I'd recommend looking at the Unity Job System instead.

Owen

On Sat, 22 Sep 2018 at 03:21, anticrisis [email protected] wrote:

@StephenHodgson https://github.com/StephenHodgson Thank you for this -- I was unable to find documentation of this after quite a bit of searching Unity's forums. Never occurred to me to just build my project and see that my async worked, and of course it did. The code you shared makes the editor work, too.

Can this technique also be used to use the thread pool to run non-UI async tasks that don't need to access the Unity API?

Does anyone know if there is official Unity documentation on this anywhere?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/svermeulen/Unity3dAsyncAwaitUtil/issues/9#issuecomment-423628689, or mute the thread https://github.com/notifications/unsubscribe-auth/AAao1NCG0BzPVpVzjNsck0ipWXtmiU75ks5udS4wgaJpZM4WcPzU .

jokigenki avatar Sep 22 '18 08:09 jokigenki

@jokigenki You should be able to use the unity api with the async approach provided here. Assuming you don't use the multithreading awaiters then it should all remain on the same thread. It should be able to be used in a very similar way to coroutines except a much cleaner syntax and some more features

svermeulen avatar Sep 22 '18 09:09 svermeulen