Contenu connexe Similaire à UniRxことはじめ (20) UniRxことはじめ18. Rxではない実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown ) {
++Count;
}
}
}
19. Rxではない実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown ) {
++Count;
}
}
}
20. Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
mouseDown.Subscribe( _ => ++Count );
}
}
21. Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
// ↑マウスが押された時にUnitが流れてくるメッセージストリームを取得
mouseDown.Subscribe( _ => ++Count );
}
}
22. Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
// ↑Unitとは何でもないものを表す(後々出てくるストリームの合成で型をあわせる為に必要)
mouseDown.Subscribe( _ => ++Count );
}
}
23. Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
// ↓イベントが流れてきたら処理を実行する
mouseDown.Subscribe( _ => ++Count );
}
}
25. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now;
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown && nextCountUp <= DateTime.Now ) {
++Count;
nextCountUp = DateTime.Now + countUpIntervalSpan;
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
}
}
26. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now; // 次回カウントアップまでの秒数管理.
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown && nextCountUp <= DateTime.Now ) {
++Count;
nextCountUp = DateTime.Now + countUpIntervalSpan;
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
}
}
27. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now;
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0); // 押されているかどうかの判定.
if ( mouseDown && nextCountUp <= DateTime.Now ) {
++Count;
nextCountUp = DateTime.Now + countUpIntervalSpan;
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
}
}
28. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now;
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown && nextCountUp <= DateTime.Now ) { // 間隔の制御.
++Count;
nextCountUp = DateTime.Now + countUpIntervalSpan;
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
}
}
29. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now;
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown && nextCountUp <= DateTime.Now ) {
++Count; // 目的の処理.
nextCountUp = DateTime.Now + countUpIntervalSpan;
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
}
}
30. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now;
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown && nextCountUp <= DateTime.Now ) {
++Count;
nextCountUp = DateTime.Now + countUpIntervalSpan; // 次のカウントアップ時間の予約.
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
}
}
31. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime nextCountUp = DateTime.Now;
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown && nextCountUp <= DateTime.Now ) {
++Count;
nextCountUp = DateTime.Now + countUpIntervalSpan;
}
else if ( false == mouseDown ) { nextCountUp = DateTime.Now; }
} // ↑離された場合のカウントアップ予約解除処理
}
32. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count );
}
}
33. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() { // ↓マウスの状態ストリーム.
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count );
}
}
34. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown // ←マウスが押されたら.
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count );
}
}
35. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
// ↑一定周期でメッセージが流れるストリームに切り換えて.
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count );
}
}
36. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
// ↓マウスが離されるまで.
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count );
}
}
37. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
// ↓マウスが離されたらもう一度押されるのを待つ.
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count );
}
}
38. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpIntervalSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown
.SelectMany( _ => Observable.Interval( countUpIntervalSpan ) )
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count ); // ←処理.
}
}
40. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime? beginCountUp = null;
private TimeSpan countUpHoldSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown ) {
if ( beginCountUp.HasValue ) {
if ( beginCountUp <= DateTime.Now ) { /* 一定間隔でカウントアップする処理 */ }
} else {
beginCountUp = DateTime.Now + countUpHoldSpan;
}
} else { beginCountUp = null; }
}
41. Rxではない実装
class Hoge : MonoBehaviour {
private DateTime? beginCountUp = null;
private TimeSpan countUpHoldSpan = TimeSpan.FromSeconds( 1 );
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown ) {
if ( beginCountUp.HasValue ) {
if ( beginCountUp <= DateTime.Now ) { /* 一定間隔でカウントアップする処理 */ }
} else {
beginCountUp = DateTime.Now + countUpHoldSpan;
}
} else { beginCountUp = null; }
}
42. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpHoldSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown.Delay( countUpHoldSpan )
.SelectMany( _ => Observable.Interval( TimeSpan.FromSeconds( 1 ) ) )
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count ); // ←処理.
}
}
43. Rxでの実装
class Hoge : MonoBehaviour {
private TimeSpan countUpHoldSpan = TimeSpan.FromSeconds( 1 );
public void Start() {
var mouseDown = gameObject.OnMouseDownAsObservable();
var mouseUp = gameObject.OnMouseUpAsObservable();
mouseDown.Delay( countUpHoldSpan )
.SelectMany( _ => Observable.Interval( TimeSpan.FromSeconds( 1 ) ) )
.TakeUntil( mouseUp ).RepeatUntilDestroy( this )
.Subscribe( _ => ++Count ); // ←処理.
}
}
49. SkipUntil/TakeUntilの動き
var s = new Subject<int>();
s.SkipUntil( x => ( 0 == ( x % 2 ) )
.TakeUntil( x => ( 0 != ( x % 2 ) )
.Subscribe( x => Debug.Log(x) );
s.OnNext( 1 );
s.OnNext( 2 );
s.OnNext( 3 );
s.OnNext( 4 );
結果 :
50. SkipUntil/TakeUntilの動き
結果 :
2で割り切れるまで読み飛ばす
var s = new Subject<int>();
s.SkipUntil( x => ( 0 == ( x % 2 ) )
.TakeUntil( x => ( 0 != ( x % 2 ) )
.Subscribe( x => Debug.Log(x) );
s.OnNext( 1 );
s.OnNext( 2 );
s.OnNext( 3 );
s.OnNext( 4 );
52. SkipUntil/TakeUntilの動き
var s = new Subject<int>();
s.SkipUntil( x => ( 0 == ( x % 2 ) )
.TakeUntil( x => ( 0 != ( x % 2 ) )
.Subscribe( x => Debug.Log(x) );
s.OnNext( 1 );
s.OnNext( 2 );
s.OnNext( 3 );
s.OnNext( 4 );
結果 :
2で割り切れるまで読み飛ばす
2で割り切れる間は続ける
2だけが出力?
53. SkipUntil/TakeUntilの動き
var s = new Subject<int>();
s.SkipUntil( x => ( 0 == ( x % 2 ) )
.TakeUntil( x => ( 0 != ( x % 2 ) )
.Subscribe( x => Debug.Log(x) );
s.OnNext( 1 );
s.OnNext( 2 );
s.OnNext( 3 );
s.OnNext( 4 );
結果 :
出力なし
55. SkipUntil/TakeUntilの動き
var s = new Subject<int>();
s.SkipUntil( x => ( 0 == ( x % 2 ) )
.TakeUntil( x => ( 0 != ( x % 2 ) )
.Subscribe( x => Debug.Log(x) );
s.OnNext( 1 );
s.OnNext( 2 );
s.OnNext( 3 );
s.OnNext( 4 );
理由 :
SkipUntilで待っている間も
TakeUntilの条件は
常にチェックされている。
62. AddTo
public static IDisposable AddTo(this IDisposable disposable, GameObject
gameObject);
public static IDisposable AddTo(this IDisposable disposable, Component
gameObjectComponent)
public static IDisposable AddTo(this IDisposable disposable,
ICollection<IDisposable> container, GameObject gameObject)
public static IDisposable AddTo(this IDisposable disposable,
ICollection<IDisposable> container, Component gameObjectComponent)
public static T AddTo<T>(this T disposable, ICollection<IDisposable>
container)
91. public event Action SomeEvent;
があった場合、
Observable.FromEvent(
h => SomeEvent += h, h => SomeEvent -= h
)
を行えばストリームに変換できます。
イベントをストリームに変換する
92. public delegate void SomeEvent();
public SomeEvent someEvent;
があった場合、
Observable.FromEvent<SomeEvent>(
h => ()=>h(), h => SomeEvent += h, h => SomeEvent -= h
) // デリゲートに変換
を行えばストリームに変換できます。
デリゲートをストリームに変換する
93. var s = new Subject<T>();
を定義して
s.OnNext(...);
で配信することができます。
s.OnCompleted();
でストリームの終了ができます。
Subjectでメッセージを配信
96. Rxではない実装
private int? previousValue = null;
void Update() {
var value = 監視したい値;
if ( previousValue.HasValue && previousValue.Value != value ) {
/* 処理 */
}
previousValue = value;
}
値の監視
98. var rp = new ReactiveProperty<T>(初期値);
があれば
IObservable<T> rpAsObservable { get { return rp; } }
で配信することができます。
配信タイミングは rp.Value = 値; などで値が書き換わった時。
ReactiveProperty<T>
99. var rp = new ReactiveProperty<T>(初期値);
また、ストリームとして以外でも
rp.Value でその時点での値が取得できます。
ReactiveProperty<T>
100. private ReactiveProperty<T> ValueProperty;
public IObservable<T> ValueAsObservable {
get { return ValueProperty; }
}
public T Value {
get { return ValueProperty.Value; }
private set { ValueProperty.Value = value; }
}
は鉄板だと思います!ぜひスニペットに登録を!
ReactiveProperty<T>
111. UniRxの作者様のブログ
株式会社グラニ 河合 宜文 様 @neuecc
http://neue.cc/category/programming/rx
その他
http://blog.xin9le.net/entry/rx-intro
http://qiita.com/toRisouP
その他お勧めな解説サイト
Notes de l'éditeur ご覧のように様々な言語でサポートされています マウスの状態を取得して、カウントアップ メッセージストリームを取得
Unitについては次のページ コメントアウト部分に先ほどまでの処理が入ります。
これだけの追加実装が必要です。 Delayというオペレータだけで実現可能です。 Subjectというものがありますが、
これはメッセージを流すものです。
詳しくは後で説明するので
一旦そういうものとして認識しておいてください。 1,2,3,4と流した時に2だけが出力されるかとおもいきや・・・ 関数型云々については 関数型云々については 関数型云々については宗教戦争になるので
納得出来ない方は流していただけるとありがたいです。 ここでは細かい構文については触れません。
細かい構文については別途ググってください。 Rx以外でも使えます。