前回はUnityの教科書chapter2を真似てUniRxをDebug.Log()でいじって遊んでみた。
今回はUnityの教科書chapter3のルーレットをUniRxベースで作ってみる。
(なぜunityの教科書のプロジェクト作ってるかは前回のを見て。)
ルーレットと針の画像をインポートしてシーンに配置
では、スクリプトを書いていこう。
ルーレットを作る。
設計
ルーレットの動作だけど、Unityの教科書では1、GameStartと同時にある一定速度でルーレットが回転
2、クリックしたら減速する
という動作である。
そのまま作っても良いけど、ちょっとアレンジして
1、GameStartでルーレットが停止状態から加速。
2、ある速度になったら回転速度固定。
3、速度が一定になったらクリック入力を受け付ける
4、クリックで減速
にする。2、ある速度になったら回転速度固定。
3、速度が一定になったらクリック入力を受け付ける
4、クリックで減速
完成品
設計通りUniRxでプログラムを書くとこんな感じになった。— 2357 (@95s7k84695a) April 19, 2020
このツイートでも言っているが、きれいに処理を隠蔽することができた。
また、それだけでなく、隠蔽した処理の部分もかなりわかりやすく書くことができた。
スクリプト全体
このスクリプトははじめてのUniRxの64ページを参考にした。using System.Collections; using UnityEngine; using UniRx; using System; public class RouletteController :MonoBehaviour { [SerializeField] private float maxSpeed = 1000, acceleration = 1.1f, deceleration = 0.99f; void Start() { Observable.FromCoroutine<float>(observer => RouletteSystem(observer, maxSpeed, acceleration, deceleration)) .Subscribe(speed => transform.Rotate(0, 0, speed * Time.deltaTime)); } IEnumerator RouletteSystem(IObserver<float> observer, float _maxSpeed, float _acceleration, float _deceleration) { float currentSpeed = 1; //ルーレットの加速 while (currentSpeed < _maxSpeed) { currentSpeed *= _acceleration; observer.OnNext(currentSpeed); yield return null; Debug.Log(currentSpeed); } currentSpeed = _maxSpeed; observer.OnNext(currentSpeed); //ストップの入力待ち bool Continue = true; while (Continue) { if (Input.GetMouseButtonDown(0)) { Continue = false; observer.OnNext(_maxSpeed); } observer.OnNext(_maxSpeed); Debug.Log(currentSpeed); yield return null; } //減速処理 while (currentSpeed > 1) { currentSpeed *= _deceleration; observer.OnNext(currentSpeed); yield return null; Debug.Log(currentSpeed); } observer.OnNext(0); observer.OnCompleted(); } }
スクリプト解説
Start()
Observable.FromCoroutine<float>(/*省略*/)これは引数のコルーチンをObservable(ストリーム)に変換するメソッドで、返り値はfloat
詳しくは
Observable.FromCoroutine<T>()
返り値 : IObservable<T>
第一引数 : Func coroutine コルーチン本体
第二引数 : bool nullAsNextUpdate = true nullの時にOnNextを発行しない,default = true
.Subscribe(speed => transform.Rotate(0, 0, speed * Time.deltaTime));
で関数を登録。
登録した関数は
引数 speed(float型)
内容 transform.transform.Rotate(0, 0, speed * Time.deltaTime));
Start()で、Observable(ストリーム)を定義した。
これは、ただ定義しただけなので、OnNext()などで呼ばれないと実行されない。
コルーチン
コルーチン内でOnNext()している。あと、最後にOnCompleted()を呼んでObservebleを片付けることを忘れないように。
引数は
IObserver<float> observer
ー 先ほどStart()で定義したObservable
float _maxSpeed
ー ルーレットの回転の最大速度
float _acceleration
ー ルーレットの加速割合
float _deceleration
ー ルーレットの減速割合
OnNext()によって、先ほどのObservableに登録した関数が実行される。ー 先ほどStart()で定義したObservable
float _maxSpeed
ー ルーレットの回転の最大速度
float _acceleration
ー ルーレットの加速割合
float _deceleration
ー ルーレットの減速割合
登録した関数は引数にfloat型の引数をとる関数なので、OnNext()で、floatの値を送る。
この送るfloatの値を状況によって変化させることでルーレットの回転速度を変化させている。
さらにその状況はコルーチンに書いたことで、上から下へ流れるように1つ1つ分けて書くことができ、非常にわかりやすくなった。
まとめ(感想)
今回はUniRxを使ってコルーチンをObservable(ストリーム)に変換した。これによって、Update()や、状況(State)を保持するメンバをなくし、処理の流れがわかりやすくなった。
また、Observableの複雑な処理をコルーチンに書いたので、Start()での実装もシンプルになった。
次回は Uniyの教科書chapter4 の寸止めゲーム、「SwipeCar」をUniRxベースで作っていこうと思う。
次回(未作成)
-今回のUnityプロジェクト-
0 件のコメント:
コメントを投稿