UnityWebRequestのダウンロード進捗率の表示をMV(R)Pで実装する【UniTask 2版】
以前,上記の記事を出しました.こちらのUniTask 2版を作りました.
UniTask 2
UniTask ver 2(以下,UniTask 2)が今月頭にリリースされました.
UniTask v2リリースしました!ゼロアロケーションで性能向上&新機能盛り沢山です。原理も厚く解説したので、是非読んで使ってください。 / “UniTask v2 – Unityのためのゼロアロケーションasync/awaitと非同期LINQ | Cygames Engineers' Blog” https://t.co/bc4rYjTjpg
— neuecc (@neuecc) 2020年6月4日
昨日,下記の勉強会にとりすーぷさんが「UniTaskの使い方2020」について発表しておりました.
50分というボリュームで発表されていたので,Unityの非同期処理をやるなら必見.
動画も公開されましたー。スライド資料と合わせて御覧ください。
— とりすーぷ (@toRisouP) 2020年6月27日
UniTaskの使い方2020
[スライド]https://t.co/8JuIaomfRk
[動画]https://t.co/YNOi5gErPr
#csharptokyo
UniTask 2 qiita まとめ.
使用環境
Unity 2019.4.0f1 UniRx 6.2.2 UniTask 2.0.21
ProgressModel
UniTask と UniTask 2で比較します.
ProgressModel.cs (UniTask)
using System; using UnityEngine; using UniRx; using UniRx.Async; using UnityEngine.Networking; public class ProgressModel : MonoBehaviour { private ReactiveProperty<float> _downloadProgress = new ReactiveProperty<float>(); public IReadOnlyReactiveProperty<float> DownloadProgress => _downloadProgress; public async void DownloadContent() { // 取得したいコンテンツのURL var url = "https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.dmg"; // テキストデータの取得 var textData = await DownloadTextAsync(url); // テキストデータの表示 Debug.Log(textData); } /// <summary> /// コンテンツのダウンロード非同期処理 /// </summary> /// <param name="url">URL</param> /// <returns>コンテンツのテキストデータ</returns> private async UniTask<string> DownloadTextAsync(string url) { using (UnityWebRequest uwr = UnityWebRequest.Get(url)) { // 送受信開始 await uwr.SendWebRequest() .ConfigureAwait(Progress.Create<float>(x => { // 値の変化を設定 _downloadProgress.Value = x * 100; // コンソール確認用 Debug.Log($"{x * 100} %"); })); // エラーハンドリング if (uwr.isNetworkError || uwr.isHttpError) throw new Exception(uwr.error); // ダウンロードしたコンテンツのテキストデータを返す return uwr.downloadHandler.text; } } }
ProgressModel.cs (UniTask 2)
using System; using UnityEngine; using System.Threading; using Cysharp.Threading.Tasks; // UniTask 2 から名前空間が UniRx.Async から変更 using UniRx; using UnityEngine.Networking; public class ProgressModel : MonoBehaviour { private ReactiveProperty<float> _downloadProgress = new ReactiveProperty<float>(); public IReadOnlyReactiveProperty<float> DownloadProgress => _downloadProgress; // CancellationTokenの設定 private CancellationToken _token; private void Awake() { // Destroy時にキャンセルされるCancellationTokenを取得 _token = this.GetCancellationTokenOnDestroy(); } public async void DownloadContent() { // 取得したいコンテンツのURL var url = "https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.dmg"; // テキストデータの取得 var textData = await DownloadTextAsync(url); // テキストデータの表示 Debug.Log(textData); } /// <summary> /// コンテンツのダウンロード処理 /// </summary> /// <param name="url">URL</param> /// <returns>コンテンツのテキストデータ</returns> private async UniTask<string> DownloadTextAsync(string url) { using (var uwr = UnityWebRequest.Get(url)) { // 送受信開始 await uwr.SendWebRequest() .ToUniTask(Progress.Create<float>(x => // 値の変化を設定 _downloadProgress.Value = x * 100), // cancellationToken: のラベルはつけること cancellationToken: _token); // エラーハンドリング if (uwr.isNetworkError || uwr.isHttpError) throw new Exception(uwr.error); // ダウンロードしたコンテンツのテキストデータを返す return uwr.downloadHandler.text; } } }
変更点
名前空間の変更
名前空間が UniRx.Async
から Cysharp.Threading.Tasks
に変更されてます.
フォルダの階層も変わってますね.
今までは Assets > UniRx.Async
に配置されてましたが,
UniTask 2から Assets > Plugins > UniTask
になりました.
AsyncOperationをawaitするときのConfigureAwait廃止
上の記事にも書かれておりますが,AsyncOperationをawaitするときに利用できていたConfigureAwaitが廃止. 実際にやってみるとこんなエラーが出ます.
ToUniTask()
を利用します.
引数の順番的にCancellationTokenを引数に持つためには,ラベル(cancellationToken:
)をつけるのが必要です.
つけないとエラーが出ます.
ProgressPresenter と ProgressView
ProgressViewとProgressPresenterはver 1と変わりません.
ProgressView.cs
using System; // IObservableの利用に必要 using UnityEngine; using UnityEngine.UI; using UniRx; public class ProgressView : MonoBehaviour { [SerializeField, Tooltip("ダウンロード進捗率表示用のUI")] private Text _text; [SerializeField, Tooltip("ダウンロードボタン")] private Button _button; private IObservable<Unit> _onDownloadButtonPushed => _button.OnClickAsObservable(); public IObservable<Unit> OnDownloadButtonPushed => _onDownloadButtonPushed; /// <summary> /// ダウンロード進捗率を整数表示する /// </summary> /// <param name="progress"></param> public void DisplayProgress(float progress) { _text.text = progress.ToString("F0") + " %"; } }
ProgressPresenter.cs
using UnityEngine; using UniRx; [RequireComponent(typeof(ProgressModel))] [RequireComponent(typeof(ProgressView))] public class ProgressPresenter : MonoBehaviour { // Extenjectを用いる方が良い [SerializeField] private ProgressModel _progressModel; [SerializeField] private ProgressView _progressView; void Start() { // Viewにあるダウンロードボタンの押下時、Modelに通知する _progressView.OnDownloadButtonPushed.Subscribe(_ => _progressModel.DownloadContent()); // Modelにある進捗率の値が変化した時、Viewに通知する _progressModel.DownloadProgress.Subscribe(_progressView.DisplayProgress); } }
動作確認
無事動きました. 引き続きUniTask 2の資料を読んで使いこなしたいと思います.