はじめに
Utilのような共通処理や、staticメソッド、Unityのイベント関数を使わない時など、
MonoBehaviourを継承する必要のないシチュエーションに出くわすことがあるでしょう。
とはいえ、MonoBehaviourを継承しないとコルーチンが使えず四苦八苦することもきっとあると思います。
MonoBehaviourを継承すれば済むのであれば継承してしまうのが良いと思いますが、そうもいかないこともあったりするので、調べた内容を残してみた。
呼び出し元クラスからMonoBehaviour型を受け取る
今回はこの方法で対応。対象となる箇所が少なく、条件もマッチしたためこの方法を採用した
MonoBehaviorを継承したクラスからthisを引数として渡すことで、
呼ばれた側はMonoBehaviour型として受け取ることができます。
引数からStartCoroutineにアクセスすることができます。
実際のサンプルコードはこんな感じ
Controller.cs
public class MainController : MonoBehaviour
{
void Start()
{
ApiUtils.CallGet(this, (apiResult) =>
{
Debug.Log(apiResult);
});
}
}
ApiUtils.cs
public class ApiUtils
{
public static void CallGet(MonoBehaviour mono, Action<bool> callback)
{
mono.StartCoroutine(GetApiResult((result) =>
{
callback(result);
}));
}
static IEnumerator GetApiResult(Action<string> callback) {
using (UnityWebRequest www = UnityWebRequest.Get("http://www.hogehoge.com"))
{
yield return www.SendWebRequest();
switch (webRequest.result)
{
case UnityWebRequest.Result.Success:
callback(webRequest.downloadHandler.text);
break;
default:
Debug.Log(www.error);
callback(null);
break;
}
}
}
}
趣旨とはズレますが、MainControllerがaddされているGameObjectがActive=falseになるとコルーチンの処理も途中で止まってしまうので、注意が必要です。
他にも色々なやり方があるみたい
今回、調べた中で別の対応方法も存在しました。
状況に合わせて対応を選んでください。
① DontDestroyOnLoadにMonoBehaviourを継承したクラスをadd
GameObjectにMonoBehaviour継承してるクラスがaddされている必要があるため、
DontDestroyOnLoad配下に配置することで全てのシーンで読み込まれまれて、利用可能になります。
公式Tutorialにも書かれているやり方のようです。
こちらの記事にも書き方が載っています。
シーンを横断して同じような構成になってて、何度も呼び出したりするような場合は、このやり方が良いかも。
DontDestroyOnLoadのような、全体に影響が出るような対応の仕方がなんか気持ち悪かったので他のやり方を探すことに(完全に個人の好みの問題)
② UniRxを導入
UniRxというアセットを用いることで、コルーチンをIObservable化することができ、MonoBehaviourを継承していない状態でもコルーチンを使えるようにすることができます。(まんまここの記事を引用)
かなりスッキリとした実装になるのは魅力的。
参考元に書いてある通り、このコルーチンに限らずUniRxを導入することで便利機能を享受できそうだけど、、
ただ、完全個人での開発とかでない限りはサクッと入れちゃうというのは難しいと思います。
そこまでの熱量ではなかったりもして他のやり方を探すことに
参考
・Use coroutine inside a non MonoBehaviour class
・【Unity】MonoBehaviourを継承していないクラスでコルーチンを使う(コールバックも)
・MonoBehaviourを継承していないクラスでStartCoroutineを使う
↧