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ができない。
なのでこちらを記事をどうぞ。
