UniTask キャンセル処理
今回の記事はUniTaskを用いたキャンセル処理についてです.
前回記事
こちらのダウンロード処理中にキャンセルを加えてみた.
参考記事
UniTask ver1 時代のもの.UniTask 2でもあまり変わらない.
Model 側
CancellationTokenSource.Cancel()を使う. UniTaskの処理中にキャンセルされた場合,OperationCanceledExceptionが生じるので, そこでcatchして,例外処理が起きた時の処理を書く.
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 CancellationTokenSource _tokenSource; private UnityWebRequest unityWebRequest; private void Awake() { _tokenSource = new CancellationTokenSource(); // Destroy時にキャンセルされるCancellationTokenを取得 _token = _tokenSource.Token; } public async void DownloadContent() { // 取得したいコンテンツのURL var url = "https://public-cdn.cloud.unity3d.com/hub/prod/UnityHubSetup.dmg"; // テキストデータの取得 var textData = await DownloadTextAsync(url); } public void CancelDownload() { _tokenSource.Cancel(); } /// <summary> /// コンテンツのダウンロード処理 /// </summary> /// <param name="url">URL</param> /// <returns>コンテンツのテキストデータ</returns> private async UniTask<string> DownloadTextAsync(string url) { var uwr = UnityWebRequest.Get(url); try { using (uwr) { // 送受信開始 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; } } catch (OperationCanceledException) { Debug.LogWarning("Canceled!"); throw; } } }
View 側
Cancel用のボタンを追加.
using System; // IObservableの利用に必要 using UnityEngine; using UnityEngine.UI; using UniRx; public class ProgressView : MonoBehaviour { [SerializeField, Tooltip("ダウンロード進捗率表示用のUI")] private Text _text_Progress; [SerializeField, Tooltip("ダウンロードボタン")] private Button _button_Download; [SerializeField, Tooltip("Cancelボタン")] private Button _button_Cancel; private IObservable<Unit> _onDownloadButtonPushed => _button_Download.OnClickAsObservable(); public IObservable<Unit> OnDownloadButtonPushed => _onDownloadButtonPushed; private IObservable<Unit> _onCancelButtonPushed => _button_Cancel.OnClickAsObservable(); public IObservable<Unit> OnCancelButtonPushed => _onCancelButtonPushed; /// <summary> /// ダウンロード進捗率を整数表示する /// </summary> /// <param name="progress"></param> public void DisplayProgress(float progress) { _text_Progress.text = progress.ToString("F0") + " %"; } }
Presenter 側
ボタン押下検知時のSubscribe の追加.
using UnityEngine; using UniRx; public class ProgressPresenter : MonoBehaviour { // Extenjectを用いる方が良い [SerializeField] private ProgressModel _progressModel; [SerializeField] private ProgressView _progressView; void Start() { // Viewにあるダウンロードボタンの押下時、Modelに通知する _progressView.OnDownloadButtonPushed.Subscribe(_ => _progressModel.DownloadContent()); // ViewのCancelボタン押下時にModelに通知する _progressView.OnCancelButtonPushed.Subscribe(_ => _progressModel.CancelDownload()); // Modelにある進捗率の値が変化した時、Viewに通知する _progressModel.DownloadProgress.Subscribe(_progressView.DisplayProgress); } }
動作確認
gyazo.com キャンセルボタンを押すと止まりました.