以前つくったゲームの処理の一部をUniRxで書き直してみた
前に作ったゲームをUniRxで一部処理を書き換えてみました。自分がどんな処理をUniRxで書き換えたのか記載します。
使用した環境は以下
- Unity 2018.1.3f1
- UniRx 6.1.2
今回やってみたこと
今まで、手続きてきな処理で実装していましたが、UniRxを使用すると諸々きれいにかけると聞いて、UniRxを使って書き換えを行ってみました。
カウントダウンの処理を書き換え
qiita.com
やりたいことがほぼ↑に書いてあることだったので、参考にしました。
ゲームをしていると、カウントダウンタイマーが欲しくなってくることが多いと思います。今までだと、だいたいコルーチンで処理を書いていましたが、これをUniRxで書き直すと
IEnumerator PlayTimeCountCoroutine() { while (_PlayTime >= 0) { yield return new WaitForSeconds(1); _PlayTime -= 1; } }
private IObservable<int> CreateCountDownObservable(int CountTime) { return Observable .Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1)) .Select(x => (int)(CountTime - x)) .TakeWhile(x => x > 0); }
こうなりました。Timerで秒数を指定して、Selectで値を計算し、TakeWhileでその値が0より大きい間は繰り返し処理をさせる書き方です
呼び出しは下記の様に行っています。
///<summury> ///開始までのカウントダウン ///</summury> public IObservable<int> GameStartCountDownObservable { get; private set; } var startConnectableObservable = CreateCountDownObservable(3).Publish();
カウントダウン処理は、開始までの時間とプレイ中の時間など同じストリームを複数回呼ぶことになるので、PublishでHotに変換しています。
ゲーム内の 処理の直列化
今までだと、ゲームを開始・プレイ中・終了を管理用変数を用意して管理していました。ただ、今回はそれをなくそうという目的でUniRxで書き換えてみました。特にポイントとしては、開始→プレイ中→終了と状態が遷移していくので処理が直列になることです。下記が今までの状態です。
switch (_Playstatus) { case PLAY_START: //プレイ開始時の処理。主に開始までのカウントダウンを実行。今回だと3sカウントしてその後実行してます。 break; case PLAY: //プレイ中の処理。ここではプレイ時間をカウントしたり、クリア時の処理・タイムアップ時の処理を記載しています。 break; case PLAY_END: //プレイ終了時の処理。ここでは、プレイ終了したらゲーム→メニューにシーン遷移するため、色々な変数を初期化しています break;
今回は例として、スタート時点の処理を記載します。
///<Summary> ///3s のカウントダウンのあとに、ゲームを開始する ///</Summary> GameStartCountDownObservable .Take(4) .Subscribe(time => m_Countdown.text = time.ToString(), () => { m_Countdown.text = "PLAY START"; _Timer = 0; _Playstatus = PLAY; displayConnectableObservable.Connect(); });
全体的な処理の都合上Take(4)を使用して最初の4つしか値を通していないのですが、これはおいといて、今まで書いていた処理をSubscribe内にまとめて、最後にdisplayConnectableObservable.Connect();で次の処理のストリームを稼働しています。今回は、処理①が終わったら処理②を行うといった流れにしたかったのでこの次にdisplayConnectableObservableのSubscribeが書かれています。こうすることで処理を直列化できます
感想
- 結局手続きてきな処理になってしまっているので、もっと宣言的に書き直したほうがよい?