はじめに
こんにちは! Life is Tech! メンターのダイキチです。
2023年も残りわずかとなりましたが、いかがお過ごしでしょうか?
僕はお正月のおみくじで 大吉 を引くためにウォーミングアップを始めました。(?)
さて、この記事は Life is Tech ! Advent Calendar 2023 の21日目の記事です。
今回はUniRxのDisposable.Create(Action disposeAction)及びCompositeDisposableについて、サンプルコードを書きながら紹介します。
Disposable.Create(Action disposeAction)を使ってみよう!
早速ですが、Unityでカメラの追従を実装するために、カメラの親子関係を管理するCameraHandlerクラスを以下のように作ったとしましょう。
using UnityEngine;
public interface ICameraHandler
{
/// <summary>
/// 親子関係を構築
/// </summary>
/// <param name="parent"></param>
void SetParent(GameObject parent);
/// <summary>
/// 親子関係を解除
/// </summary>
void Release();
}
public class CameraHandler : MonoBehaviour, ICameraHandler
{
/// <summary>
/// メインカメラ
/// </summary>
[SerializeField]
private GameObject m_MainCamera;
/// <summary>
/// カメラを追従させる
/// </summary>
/// <param name="parent"></param>
void ICameraHandler.SetParent(GameObject parent)
{
m_MainCamera.transform.SetParent(parent.transform);
}
/// <summary>
/// カメラの追従を止める
/// </summary>
void ICameraHandler.Release()
{
m_MainCamera.transform.parent = null;
}
}
/// <summary>
/// 利用者側のサンプルコード
/// </summary>
public class Player : MonoBehaviour
{
private ICameraHandler m_CameraHandler;
public void SetParent()
{
m_CameraHandler.SetParent(this.gameObject);
}
public void Release()
{
m_CameraHandler.Release();
}
}
ICameraHandler は親子関係の構築と解除のメソッドを提供しています。
このままでも十分使えますが、ここでDisposable.Create(Action disposeAction)を使った実装に作り変えてみると、以下のようになります。
using UnityEngine;
using System;
using UniRx;
public interface ICameraHandler
{
/// <summary>
/// 親子関係を構築
/// </summary>
/// <param name="parent"></param>
/// <returns>親子関係を解除</returns>
IDisposable SetParent(GameObject parent);
}
public class CameraHandler : MonoBehaviour, ICameraHandler
{
/// <summary>
/// メインカメラ
/// </summary>
[SerializeField]
private GameObject m_MainCamera;
/// <summary>
/// カメラを追従させる
/// </summary>
/// <param name="parent"></param>
/// <returns>親子関係を解除</returns>
IDisposable ICameraHandler.SetParent(GameObject parent)
{
m_MainCamera.transform.SetParent(parent.transform);
return Disposable.Create(() => m_MainCamera.transform.parent = null);
}
}
/// <summary>
/// 利用者側のサンプルコード
/// </summary>
public class Player : MonoBehaviour
{
private ICameraHandler m_CameraHandler;
private IDisposable m_CameraRelease;
public void SetParent()
{
if (m_CameraRelease != null)
{
#if DEBUG
Debug.LogWarning("親子関係はすでに構築済みです。");
#endif
return;
}
m_CameraRelease = m_CameraHandler.SetParent(this.gameObject);
}
public void Release()
{
m_CameraRelease?.Dispose(); // IDiposableを使って親子関係を解除
m_CameraRelease = null;
}
}
主な変更点は、ICameraHandlerから提供されるメソッドがIDisposable SetParent(GameObject parent)のみになったことです。
戻り値のIDisposableには、カメラとの親子関係を解除する処理が入っていて、これはDisposable.Create(Action disposeAction)を使って作成しています。
こうすることで利用者側は、戻り値のIDisposableをメンバ変数で覚えておくことで、ICameraHandlerを介さずに親子関係の解除をすることができるようになりました。
CompositeDisposableを使ってみよう!
Disposable.Create(Action disposeAction)で作成したIDisposableを戻り値にすると、利用者側に終了処理を教えることができるということが伝わったかと思います。
しかし、実際に開発をしていると複数のIDisposableを扱いたくなるときがあります。そんなときはCompositeDisposableを使いましょう。
/// <summary>
/// 利用者側のサンプルコード
/// </summary>
public class Player : MonoBehaviour
{
private ICameraHandler m_CameraHandler;
private IDummyHandler m_DummyHandler;
private CompositeDisposable m_CompositeDisposable = new CompositeDisposable();
public void SetParent()
{
var cameraDisposable = m_CameraHandler.SetParent(this.gameObject);
m_CompositeDisposable.Add(cameraDisposable);// IDisposableを登録
var dummyDisposable = m_DummyHandler.DummyMethod();
m_CompositeDisposable.Add(dummyDisposable); // IDisposableを登録
}
public void Release()
{
m_CompositeDisposable.Clear(); // IDisposableをまとめてDispose
}
}
void Add(IDisposable item)でIDisposableをCompositeDisposableに登録できます。
また、void Clear()で登録したIDisposableをまとめてDisposeできます。このとき、登録されていたIDisposableは全て破棄されます。
おわりに
今回は UniRxのDisposable.Create(Action disposeAction)及びCompositeDisposableについて紹介しました。
細かい説明は端折って解説してしまったので、より詳しいことを知りたい方はこの後に載っている参考文献をお読みください。
さて、明日の Life is Tech ! Advent Calendar 2023 は みったに先生の記事になります。
どうやらUI演出についての記事のようです。楽しみですね!!
以上、Life is Tech! メンターのダイキチでした。またね〜!
参考文献