【UniRx】AsyncSubjectで初期化の順番を分かりやすく記述する
初期化処理ってとにかく順番が命で、ちょっとでもミスるとエラーまみれになってしまいがちです。特にロードしきれてないのに呼び出しちゃってnull参照エラーになることはよくあります(あるな)。
最近Awake()やStart()がテキトーに呼ばれているという事実を目の当たりにし、ちゃんと初期化処理書かないと痛い目見るな...となったのですが、あまりいい方法が分からず。
一応下記ブログのようにしてStart()の実行順序を変えることもできるのですが、結構面倒だし、動的に生成されるものについても考えると大変です(方法として知っておくのは大事だけど)。 bluebirdofoz.hatenablog.com
というわけで、本題。
AsyncSubject
参考記事↓
UniRxの機能であるAsyncSubject
は、OnComplete
時に最後にOnNext
された値のみを発行するSubject
です。普通のSubject
とは違い、機能が限定されている分、目的が明確になって分かりやすく初期化処理を書くことが出来ます。
以下に初期化の例を記述します。
例
public class Player : MonoBehaviour { // 初期化が終わったかを監視するSubject public IObservable<Unit> OnInitializeAsync => _onInitializeAsyncSubject; private readonly AsyncSubject<Unit> _onInitializeAsyncSubject = new(); private void Awake() { // Playerの初期化処理(ステータス、各種GetComponentなど) // Awakeの最後にOnNextとOnCompletedを発行 _onInitializeAsyncSubject.OnNext(Unit.Default); _onInitializeAsyncSubject.OnCompleted(); } }
public class SomethingPlayerComponent : MonoBehaviour { private Player _player; private void Start() { _player = GetComponent<Player>(); // Playerの初期化が終わったらOnPlayerInitialized()を実行する _player.OnInitializeAsync .Subscribe(_ => OnPlayerInitialized()); } private void OnPlayerInitialized() { // Playerが初期化されているのでPlayerから何かを取得してもnull参照にならない(初期化で不足がある場合を除く) } }
Player
クラスにて各種コンポーネントの取得等の初期化処理をしたとき、コンポーネント側で初期化を待てるようにしたい、という場合が多くあると思います。
そういった際にはうってつけだと思うので是非。
(なんかでももっといい機能ありそうなんだよな...)