少し前にどころか、数か月前に Unity で画像を取得する方法を調べた続きです。
前々回に Web Request を コルーチン で待機し、前回に Async/Await で待機しました。
今回は、前回作った Async/Await なメソッド を コルーチン で待機しようと思います
コルーチン対応のメソッドも追加
using System; using System.Collections; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class WebRequester : MonoBehaviour { [SerializeField] private RawImage _rawImage; public async void OnClickGetTexture() { try { var texture = await GetTexture("https://picsum.photos/200"); _rawImage.texture = texture; } catch (Exception ex) { Debug.LogError($"[WebRequester:ERROR] {ex.Message}"); } } + public void OnClickGetTextureCoroutine() + { + StartCoroutine(GetTextureCoroutine("https://picsum.photos/200", (texture) => + { + _rawImage.texture = texture; + }, (error) => + { + Debug.LogError($"[WebRequester:ERROR] {error}"); + })); + } private async Task<Texture2D> GetTexture(string url) { using var req = UnityWebRequestTexture.GetTexture(url); Debug.Log("[WebRequester] Send"); req.SendWebRequest(); Debug.Log("[WebRequester] Recv"); while (!req.isDone) { // 50ms 待機 await Task.Delay(50); } if (req.result == UnityWebRequest.Result.Success) { var texture = DownloadHandlerTexture.GetContent(req); return texture; } else { throw new Exception(string.IsNullOrEmpty(req.downloadHandler.error) ? req.error : req.downloadHandler.error); } } + private IEnumerator GetTextureCoroutine(string url, Action<Texture2D> successCallback = null, Action<string> errorCallback = null) + { + var task = GetTexture(url); + + while (!task.IsCompleted) + { + // 50ms 待機 + yield return new WaitForSeconds(0.05f); + } + + try + { + successCallback?.Invoke(task.Result); + } + catch (Exception ex) + { + errorCallback?.Invoke(ex.Message); + } + } + }
await はできないので、Task が IsCompleted
になるまで待ち続けます。ちなみにエラーになっても IsCompleted
は true
になるようです。
エラーが発生している場合は、
task.Result
にアクセスするときに Exception が送出されるっぽい
スクリプト全体
(折りたたみ)
using System; using System.Collections; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class WebRequester : MonoBehaviour { [SerializeField] private RawImage _rawImage; public async void OnClickGetTexture() { try { var texture = await GetTexture("https://picsum.photos/200"); _rawImage.texture = texture; } catch (Exception ex) { Debug.LogError($"[WebRequester:ERROR] {ex.Message}"); } } public void OnClickGetTextureCoroutine() { StartCoroutine(GetTextureCoroutine("https://picsum.photos/200", (texture) => { _rawImage.texture = texture; }, (error) => { Debug.LogError($"[WebRequester:ERROR] {error}"); })); } private async Task<Texture2D> GetTexture(string url) { using var req = UnityWebRequestTexture.GetTexture(url); Debug.Log("[WebRequester] Send"); req.SendWebRequest(); Debug.Log("[WebRequester] Recv"); while (!req.isDone) { // 50ms 待機 await Task.Delay(50); } if (req.result == UnityWebRequest.Result.Success) { var texture = DownloadHandlerTexture.GetContent(req); return texture; } else { throw new Exception(string.IsNullOrEmpty(req.downloadHandler.error) ? req.error : req.downloadHandler.error); } } private IEnumerator GetTextureCoroutine(string url, Action<Texture2D> successCallback = null, Action<string> errorCallback = null) { var task = GetTexture(url); while (!task.IsCompleted) { // 50ms 待機 yield return new WaitForSeconds(0.05f); } try { successCallback?.Invoke(task.Result); } catch (Exception ex) { errorCallback?.Invoke(ex.Message); } } }
シーンにボタンを追加
右のボタンを押したら StartCoroutine を実行するメソッドを動かします!
右のボタンのクリックリスナーの設定
動作確認
両方動いている!
まとめ
これでどっちでもいけるようになった