ã¯ããã«
http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/
ãã®è¨äºã¯ãä¸è¨ã®ãã¼ã¸ã§å
¬éããã¦ãã
Unity 2017 ã§ã³ã«ã¼ãã³ã®ä»£ããã«
async / await ã使ç¨ããæ¹æ³ã翻訳ãããã®ã«ãªãã¾ã
ç®æ¬¡
- ã¯ããã«
- ç®æ¬¡
- ã³ã«ã¼ãã³
- async / await
- ç°¡åãªä¾
- Custom Awaiters
- AsyncAwaitUtil.unitypackage
- ä¾å¤å¦ç
- ã³ã«ã¼ãã³ããéåæã¡ã½ããå¼ã³åºã
- è¤æ°ã®ã¹ã¬ãã
- UniRx ã¨éåæãã¸ãã¯ã®é£æº
ã³ã«ã¼ãã³
ã³ã«ã¼ãã³ã¯ä¾¿å©ã§ãããããã¤ãã®æ¬ ç¹ãããã¾ã
- ã³ã«ã¼ãã³ã¯å¤ãè¿ããã¨ãã§ãã¾ãã
ãã®ãããAction åã®ã³ã¼ã«ããã¯ãå¼æ°ã§æ¸¡ããªã©ã®å¯¾å¿ãå¿ è¦ã«ãªãã¾ã
ã - try-catch å
ã« yield ãå
¥ãããã¨ã¯ã§ããªãã®ã§ãä¾å¤ãå¦çã§ãã¾ãã
ã¾ããä¾å¤ãçºçããå ´åãã¹ã¿ãã¯ãã¬ã¼ã¹ã«ã¯
ä¾å¤ãæããããã³ã«ã¼ãã³ãéç¥ãããã ããªã®ã§ã
å¼ã³åºãå ãæ¨æ¸¬ããå¿ è¦ãããã¾ã
async / await
Unity 2017 ã§ã¯ async / await ã¨ããæ°ãã C# ã®æ©è½ã使ããããã«ãªãã¾ãã
ããã¯ãã³ã«ã¼ãã³ã¨æ¯ã¹ã¦ããããã®ç´ æ´ãããæ©è½ãç¨æããã¦ãã¾ã
ãã®æ©è½ãæå¹ã«ããã«ã¯ãUnity ã¡ãã¥ã¼ã®ãFile>Build Settings...ããã
ãPlayer Settingsããé¸æãããScripting Runtime Versionãã
ãExperimental (.NET 4.6 Equivalent)ãã«å¤æ´ããå¿
è¦ãããã¾ã
ç°¡åãªä¾
ããã§ã¯ã³ã«ã¼ãã³ã¨ async / await ãç°¡åã«æ¯è¼ãã¦ã¿ã¾ã
ã¾ãã¯ã³ã«ã¼ãã³ã®ä½¿ç¨ä¾ã§ã
using System.Collections; using UnityEngine; public class Example : MonoBehaviour { private IEnumerator Start() { Debug.Log( "1ç§å¾ ã¤..." ); yield return new WaitForSeconds( 1f ); Debug.Log( "å®äºï¼" ); } }
次ã¯ãasync / await ã®ä½¿ç¨ä¾ã«ãªãã¾ã
using System; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private async void Start() { Debug.Log( "1ç§å¾ ã¤..." ); await Task.Delay( TimeSpan.FromSeconds( 1 ) ); Debug.Log( "å®äºï¼" ); } }
ã³ã«ã¼ãã³ã使ç¨ããã³ã¼ãã¯ããã®ããã« async / await ã«ç½®ãæãããã¨ãã§ãã¾ã
Custom Awaiters
åè¿°ãã async / await ã®ãµã³ãã«ã³ã¼ãã§ã¯ã
await Task.Delay( TimeSpan.FromSeconds( 1 ) );
1ç§å¾ æ©ããã³ã¼ããå°ãåé·ã§ãããã
using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; public static class TimeSpanExt { public static TaskAwaiter GetAwaiter( this TimeSpan self ) { return Task.Delay( self ).GetAwaiter(); } }
ãã®ãããªæ¡å¼µã¡ã½ãããå®ç¾©ãããã¨ã§
await TimeSpan.FromSeconds( 1 );
TimeSpan ãç´æ¥ä½¿ç¨ãã¦1ç§å¾ æ©ããã³ã¼ãããã®ããã«è¨è¿°ã§ããããã«ãªãã¾ã
AsyncAwaitUtil.unitypackage
ä¸è¨ã®ãã¼ã¸ã§å
¬éããã¦ãã
AsyncAwaitUtil.unitypackage ãããã¸ã§ã¯ãã«å°å
¥ããã¨ã
Unity ãç¨æãã¦ãã WaitForEndOfFrameãWaitForSecondsãWWW ãªã©ã
async / await ã§ä½¿ç¨ã§ããããã«ãªãã¾ã
using System.Collections; using System.Diagnostics; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; public class Example : MonoBehaviour { private async void Start() { // 1ãã¬ã¼ã å¾ ã¤ await new WaitForEndOfFrame(); // 1ç§å¾ 㤠await new WaitForSeconds( 1f ); // 1ç§å¾ ã¤ï¼Time.timeScale ã¯ç¡è¦ï¼ await new WaitForSecondsRealtime( 1f ); // ã³ã«ã¼ãã³ã®å®äºãå¾ ã¤ await Wait(); // ã³ã«ã¼ãã³ã®å®äºãå¾ æ©ãã¦æ»ãå¤ãåãåã var value = ( string )( await WaitWithValue() ); // ã·ã¼ã³ã®èªã¿è¾¼ã¿ãå¾ ã¤ await SceneManager.LoadSceneAsync( "" ); // ãªã½ã¼ã¹ã®èªã¿è¾¼ã¿ãå¾ ã¤ var prefab = await Resources.LoadAsync<GameObject>( "" ); // ã¢ã»ãããã³ãã«ã®ãã¦ã³ãã¼ããå¾ ã¤ var ab = ( await new WWW( "" ) ).assetBundle; // ã¢ã»ãããã³ãã«ããã¢ã»ããã®èªã¿è¾¼ã¿ãå¾ ã¤ var mat = ab.LoadAssetAsync<Material>( "" ); // HTTP éä¿¡ã®å®äºãå¾ ã¤ var request = UnityWebRequest.Get( "" ); await request.SendWebRequest(); var data = request.downloadHandler.data; // ããã°ã©ã ãèµ·åãã¦çµäºãå¾ ã¤ var returnCode = await Process.Start( "" ); } private IEnumerator Wait() { yield return new WaitForSeconds( 1f ); } private IEnumerator WaitWithValue() { yield return new WaitForSeconds( 1f ); yield return "ãã«ãã¥ã¦"; } }
ä¾å¤å¦ç
using System; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private void OnGUI() { if ( GUILayout.Button( "ã¿ã¹ã¯éå§" ) ) { RunTaskAsync(); } } private async Task RunTaskAsync() { await new WaitForSeconds( 1f ); throw new Exception(); // ããã§ä¾å¤çºç } }
ä¾ãã°ããã¯ããã¿ã³ãæ¼ãããæã«éåæã¡ã½ãããéå§ããã
1ç§å¾ã«ä¾å¤ãçºçããã³ã¼ãã§ã
ããããUnity ã§å®è¡ããã¨ä¾å¤ãæ¤ç¥ãããªããã¨ããããã¾ã
ä¾å¤ãæ¤ç¥ããããã«ã¯ä¸è¨ã®ãããªã³ã¼ãã«å¤æ´ãã¾ã
using System; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private void OnGUI() { if ( GUILayout.Button( "ã¿ã¹ã¯éå§" ) ) { RunTask(); } } private async void RunTask() { await RunTaskAsync(); } private async Task RunTaskAsync() { await new WaitForSeconds( 1f ); throw new Exception(); // ããã§ä¾å¤çºç } }
ãã®ããã«ãasync void ã®é¢æ°ãéã«æããã¨ã§ãä¾å¤ãæ¤ç¥ã§ããããã«ãªãã¾ã
using System; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private void OnGUI() { if ( GUILayout.Button( "ã¿ã¹ã¯éå§" ) ) { RunTaskAsync().WrapErrors(); } } private async Task RunTaskAsync() { await new WaitForSeconds( 1f ); throw new Exception(); // ããã§ä¾å¤çºç } }
åè¿°ãã AsyncAwaitUtil.unitypackage ãããã¸ã§ã¯ãã«å°å
¥ããå ´åã¯ã
ãã®ããã« WrapErrors é¢æ°ã使ç¨ãã¦ä¾å¤ãæ¤ç¥ãããã¨ãå¯è½ã§ã
ã³ã«ã¼ãã³ããéåæã¡ã½ããå¼ã³åºã
using System.Collections; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private void Start() { StartCoroutine( RunTask() ); } private IEnumerator RunTask() { yield return RunTaskAsync().AsIEnumerator(); Debug.Log( "ã«ã¤ãªã¥ã¼" ); } private async Task RunTaskAsync() { await new WaitForSeconds( 1f ); Debug.Log( "ãã«ãã¥ã¦" ); } }
AsyncAwaitUtil.unitypackage ã«å«ã¾ãã¦ãã AsIEnumerator é¢æ°ã使ç¨ããã¨ã
ã³ã«ã¼ãã³ããéåæã¡ã½ãããå¼ã³åºããã¨ãã§ãã¾ã
è¤æ°ã®ã¹ã¬ãã
async / await ã使ç¨ãã¦è¤æ°ã®ã¹ã¬ãããå®è¡ãããã¨ãã§ãã¾ã
æåã®æ¹æ³ã¯ãConfigureAwait é¢æ°ã使ããã¨ã§ã
using System; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private async void Start() { // ãã㯠Unity ã®ã¹ã¬ãããªã®ã§ã // Unity ã® API ãå®è¡ã§ãã var go1 = new GameObject(); await Task .Delay( TimeSpan.FromSeconds( 1f ) ) .ConfigureAwait( false ) ; // ããã¯å¥ã®ã¹ã¬ãããªã®ã§ã // Unity ã® API ãå®è¡ããã¨ã¨ã©ã¼ãçºçãã var go2 = new GameObject(); } }
ConfigureAwait é¢æ°ä»¥ä¸ã®ã³ã¼ã㯠Unity ã¹ã¬ããã§ã¯ãªã
å¥ã®ã¹ã¬ããã§åä½ããããã«ãªãããã
Unity API ãå¼ã³åºããªããã¨ã«æ³¨æãã¦ãã ãã
AsyncAwaitUtil.unitypackage ã使ç¨ããå ´åã¯ã
次ã®ããã«ãããã¨ãã§ãã¾ã
using System; using System.Threading.Tasks; using UnityEngine; public class Example : MonoBehaviour { private async void Start() { // ãã㯠Unity ã®ã¹ã¬ãããªã®ã§ã // Unity ã® API ãå®è¡ã§ãã new GameObject(); await new WaitForBackgroundThread(); // ããã¯å¥ã®ã¹ã¬ãããªã®ã§ã // Unity ã® API ãå®è¡ããã¨ã¨ã©ã¼ãçºçãã new GameObject(); await new WaitForUpdate(); // ãã㯠Unity ã®ã¹ã¬ãããªã®ã§ã // Unity ã® API ãå®è¡ã§ãã new GameObject(); } }
WaitForBackgroundThread ã§æ°ããã¹ã¬ãããéå§ãã
WaitForUpdate 㧠Unity ã®ã¹ã¬ããã«æ»ããã¨ãã§ãã¾ã
UniRx ã¨éåæãã¸ãã¯ã®é£æº
UniRx ã使ç¨ãã¦ããããã¸ã§ã¯ãã§ããã°ã
AsyncAwaitUtil.unitypackage ã«å«ã¾ãã¦ãããUniRx.zipããå±éããã¨ã
ä¸è¨ã®ãããªã³ã¼ããå®è£
ã§ããããã«ãªãã¾ã
using UniRx; using UnityEngine; using UnityEngine.UI; public class Example : MonoBehaviour { public Button m_button; private async void Start() { await m_button.OnClickAsObservable(); Debug.Log( "ãã¿ã³ãæ¼ããã" ); } }