ObservableWWW
ObservableWWW
とはUniRxでUnityEngine.WWW
をObservable
として扱える便利な機構でした。
ですがこのUnityEngine.WWW
自体がかなり古く、2019年現在では非推奨となってしまいました。
(代わりにUnityWebRequest
を使う必要がある)
それに伴い、Unity2018.3以降ではObservableWWW
がObsolete
になってしまいました。
そこで今回は、Unity2018.3以降でObservableWWW
の代替手段を紹介します。
そもそもUnity2018.3以降でObservableWWW使わなくない?
そもそも論として、Unity2018.3だとUniTaskが使えるため積極的にObservable
を利用する必要がありません。
このような単発の非同期処理であればasync/await
で十分だからです。
結論: UniTaskを使おう
ということで、結論としては「UniTaskを使う」となります。
GitHubからUniTaskを導入
UniTaskはAssetStoreでは公開されていないため、GitHubから導入する必要があります。
上記の場所から最新のUniTaskのunitypackageをダウンロードして、Unityプロジェクトに導入してください。
UniTaskというプロジェクト名ですけど、歴史的経緯でパッケージ名は「UniRx.Async」になっています。
UniTaskを使ったコードを書く
using UniRx.Async;
をした上で。WWW
の代わりにUnityWebRequest
をasync/await
で待受けるようにしてください。
using System;
using UnityEngine;
using UniRx.Async;
using UnityEngine.Networking;
public class UnityWebRequestSample : MonoBehaviour
{
async void Start()
{
var uri = "https://unity.com/";
try
{
var result = await GetTextAsync(uri);
Debug.Log(result);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
/// <summary>
/// UnityWebRequestをasync/awaitで待ち受ける
/// </summary>
private async UniTask<string> GetTextAsync(string uri)
{
var uwr = UnityWebRequest.Get(uri);
// SendWebRequestが終わるまでawait
await uwr.SendWebRequest();
if (uwr.isHttpError || uwr.isNetworkError)
{
// 失敗していたらそのまま例外をthrow
throw new Exception(uwr.error);
}
return uwr.downloadHandler.text;
}
}
これでOKです。
でもやっぱObservableがいい
諸々の諸事情により、UniTask<T>
ではなくIObservable<T>
に変換したい場合があります。
その場合はToObservable()
を用いて変換するとよいでしょう。
Hotのままでいいなら
GetTextureObservable()
を実行した時点でGetTextAsync()
が実行開始してもよいならこの方法でOKです。
/// <summary>
/// UnityWebRequestを内部で利用したObservable
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private IObservable<string> GetTextureObservable(string uri)
{
return GetTextAsync(uri).ToObservable();
}
/// <summary>
/// UnityWebRequestをasync/awaitで待ち受ける
/// </summary>
private async UniTask<string> GetTextAsync(string uri)
{
var uwr = UnityWebRequest.Get(uri);
// SendWebRequestが終わるまでawait
await uwr.SendWebRequest();
if (uwr.isHttpError || uwr.isNetworkError)
{
// 失敗していたらそのまま例外をthrow
throw new Exception(uwr.error);
}
return uwr.downloadHandler.text;
}
Coldにしたいなら
GetTextureObservable()
をSubscribe()
したタイミングで、GetTextAsync()
が実行開始して欲しいならこの方法で。
Observable.Defer()
を使ってください。
/// <summary>
/// UnityWebRequestを内部で利用したObservable
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private IObservable<string> GetTextureObservable(string uri)
{
return Observable.Defer(() => GetTextAsync(uri).ToObservable());
}
/// <summary>
/// UnityWebRequestをasync/awaitで待ち受ける
/// </summary>
private async UniTask<string> GetTextAsync(string uri)
{
var uwr = UnityWebRequest.Get(uri);
// SendWebRequestが終わるまでawait
await uwr.SendWebRequest();
if (uwr.isHttpError || uwr.isNetworkError)
{
// 失敗していたらそのまま例外をthrow
throw new Exception(uwr.error);
}
return uwr.downloadHandler.text;
}
まとめ
- UnityWebRequestを使うならUniTaskとasync/awaitで
- ObservableにしたいならUniTaskから変換する
なお、このままではCancellationToken
を引数にしていた場合ToObservable
ができない。
なのでこちらを記事をどうぞ。