SlideShare ist ein Scribd-Unternehmen logo
1 von 123
UniRxことはじめ
KLab株式会社 安井彰一
自己紹介
名前:安井彰一
経歴:コンソールゲームプログラマ5年
ネットワークゲームエンジニア3年
昨年9月 KLab入社
(Uni)Rx歴3ヶ月
本稿の対象者
Linqがある程度読める人 ( C# )
Rxの資料は読んだがまだ書いたことがない人
注釈
本稿ではUniRxを題材に扱いますが、
その他のRx実装でも同様の考え方ができます。
ただし、メソッド名などが違う場合が
ありますのでご注意ください。
アジェンダ
・(Uni)Rxとは
・Rxの利点
・Rxの問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
アジェンダ
・(Uni)Rxとは
・Rxの利点
・Rxの問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
UniRxとは
Rx(Reactive Extensions)の
Unity実装です。
Rxとは
(Reactive Extensions)
イベントの流れ及びその制御を
LINQのような書式で
簡潔に書けるようにしたもの。(意訳)
Rxの実装リスト
Rx.NET
RxJS
RxJava ( RxAndroid )
ReactiveCocoa
Rx.py
など
ReactiveExtensionsとは
プログラミング手法のこと。
C#だけのものではありません。
アジェンダ
・(Uni)Rxとは
・Rxの利点
・Rxの問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
Rxの利点
時間を簡単に扱える
例題
例題A
マウスを押しっぱなしにしている間、
数値をカウントアップさせる。
Rxではない実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown ) {
++Count;
}
}
}
Rxではない実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Update() {
bool mouseDown = Input.GetMouseButtonDown(0);
if ( mouseDown ) {
++Count;
}
}
}
Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
mouseDown.Subscribe( _ => ++Count );
}
}
Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
// ↑マウスが押された時にUnitが流れてくるメッセージストリームを取得
mouseDown.Subscribe( _ => ++Count );
}
}
Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
// ↑Unitとは何でもないものを表す(後々出てくるストリームの合成で型をあわせる為に必要)
mouseDown.Subscribe( _ => ++Count );
}
}
Rxでの実装
class Hoge : MonoBehaviour {
public int Count { get; private set; }
public void Start() {
IObservable<Unit> mouseDown = gameObject.OnMouseDownAsObservable();
// ↓イベントが流れてきたら処理を実行する
mouseDown.Subscribe( _ => ++Count );
}
}
例題A’
マウスを押しっぱなしにしている間、
一定間隔で数値をカウントアップさせる。
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; }
}
}
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; }
}
}
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; }
}
}
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; }
}
}
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; }
}
}
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; }
}
}
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; }
} // ↑離された場合のカウントアップ予約解除処理
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 );
}
}
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 ); // ←処理.
}
}
例題A’’
マウスを一定時間以上
押しっぱなしにしている間、
一定間隔で数値をカウントアップさせる。
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; }
}
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; }
}
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 ); // ←処理.
}
}
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 ); // ←処理.
}
}
Rxの利点
このように、Rxの方が時間を操作するための
オペレータが多数揃っているという点で優れています。
それ以外にもフィルタリング処理やデータの変換、
複数のストリームをマージすることができたり、
イベント処理と比べて処理を
1箇所にまとめて記述できるなど
その他の利点も多数存在します。
アジェンダ
・(Uni)Rxとは
・Rxの利点
・Rxの問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
Rxの問題点
問題点
動きが
予測しづらい
例えば
SkipUntilと
TakeUntil
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の動き
結果 :
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 );
SkipUntil/TakeUntilの動き
結果 :
2で割り切れるまで読み飛ばす
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 );
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だけが出力?
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の動き
結果 :
1が流れてきた時点で
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の動き
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の条件は
常にチェックされている。
解決策
慣れてください
Rxの各オペレータの動き
Rxにおける各オペレータは
ストリームの性質を定義しているに過ぎず、
LINQと同じ感覚で使っていると
思ったとおりに動かない。
Rxの各オペレータの動き
Rxにおける各オペレータは
ストリームの性質を定義しているに過ぎず、
LINQと同じ感覚で使っていると
思ったとおりに動かない。
⇒慣れるしかない
Rxの各オペレータの動き
Rxにおける各オペレータは
ストリームの性質を定義しているに過ぎず、
LINQと同じ感覚で使っていると
思ったとおりに動かない。
⇒慣れるしかない
http://rxmarbles.com/
問題点
購読し続ける事により
キャプチャされた
インスタンスが
解放されない
解決策
AddToという
オペレータを
使ってください
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)
AddTo
// OnDestroyで勝手に破棄
Observable...Subscribe().AddTo( this );
Observable...Subscribe().AddTo( gameObject );
// 参照を失った時やDispose()が呼ばれた時に破棄
var d = new CompositeDisposable();
Observable...Subscribe().AddTo( d );
問題点
オペレータ毎に
増えていく
メモリ使用量
解決策(?)
処理負荷との
トレードオフで検討
(GC...)
オペレータ実行時にObserverクラスが生成される。
小さなクラスが大量に生成される。 -> GC負荷が上がる。
欠点:メモリ使用量とGCのコスト
オペレータ実行時にObserverクラスが生成される。
小さなクラスが大量に生成される。 -> GC負荷が上がる。
UniRxの場合、専用のコンポーネントが生成される。
生成コストや上記と同じくGCの負荷が上がる。
欠点:メモリ使用量とGCのコスト
オペレータ実行時にObserverクラスが生成される。
小さなクラスが大量に生成される。 -> GC負荷が上がる。
UniRxの場合、専用のコンポーネントが生成される。
生成コストや上記と同じくGCの負荷が上がる。
不要なオブジェクトの参照を握り続けてしまう。(前述)
解放できない領域が残る可能性がある。 -> メモリリーク
欠点:メモリ使用量とGCのコスト
変数などに変更が加わった時だけなど
必要なときにだけ処理が実行される。
処理負荷が軽減されることを期待できる。
利点:処理負荷やバグの出難さ
変数などに変更が加わった時だけなど
必要なときにだけ処理が実行される。
処理負荷が軽減されることを期待できる。
メンバ変数などを保持する必要がなくなる。
変数の状態起因系のバグが出にくい。
利点:処理負荷やバグの出難さ
変数などに変更が加わった時だけなど
必要なときにだけ処理が実行される。
処理負荷が軽減されることを期待できる。
メンバ変数などを保持する必要がなくなる。
変数の状態起因系のバグが出にくい。
小さな関数の合成によりコーディング中のバグが出にくい。
関数型プログラミングの利点がそのまま利点に。
といっても副作用のある関数だとバグは出ます。
利点:処理負荷やバグの出難さ
問題点
とっつきにくい
解決策
慣れてください
正直、Rxはトライアンドエラーで
動作の感覚を身につけるしか
習熟する方法はないと思います。
問題点
学習コストが高い
解決策
慣れるための
環境づくり
先日のUniRx勉強会で話を聞いたところ、
LINQを知らない人の基準での学習コストは
概ね1ヶ月ほどとのことです。
また、LINQがわかるなら
もう少し短縮できるだろうとのことでした。
学習コスト
それでも
使わないとRxのコードも読めません。
そのため、
みんなでRxでコードを書こうという
チーム内での合意が必要です!
学習コスト
問題点
勉強方法
解決策
ググる
Rxについては
ReactiveExtensionsで検索すれば
解説が多数ヒットします。
UniRxについても
“UniRx”で検索すれば
(Google先生がUnixをお勧めしてくれるので)
解説が多数ヒットします。
強いて言えば
以下のサイトがお勧めです。
http://rxmarbles.com/
http://qiita.com/tags/unirx
https://unityuserj.slack.com/messages/unirx/
先日行われた
UniRx勉強会の資料
はじめてのUniRx
若輩エンジニアから見たUniRxを利用したゲーム開発
Interactive UI with UniRx
History & Practices for UniRx UniRxの歴史、
或いは開発(中)タイトルの用例と落とし穴の回避法
「ずいぶんとダサいライティングを使っているのね
〜UniRxを用いた物理ベースライティング制御〜
UniRx勉強会のまとめ
興味を持ったので
UniRxを使ってみたい
でもどこから
手を付けていいのか
わからない
ということで
アジェンダ
・(Uni)Rxとは
・Rxの利点と問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
UniRxの
導入いろは
AssetStoreからパッケージで落とす
https://www.assetstore.unity3d.com/jp/#!/content/17276
Githubからソースを落とす
https://github.com/neuecc/UniRx
UniRxをプロジェクトに追加
手の付け方
public event Action SomeEvent;
があった場合、
Observable.FromEvent(
h => SomeEvent += h, h => SomeEvent -= h
)
を行えばストリームに変換できます。
イベントをストリームに変換する
public delegate void SomeEvent();
public SomeEvent someEvent;
があった場合、
Observable.FromEvent<SomeEvent>(
h => ()=>h(), h => SomeEvent += h, h => SomeEvent -= h
) // デリゲートに変換
を行えばストリームに変換できます。
デリゲートをストリームに変換する
var s = new Subject<T>();
を定義して
s.OnNext(...);
で配信することができます。
s.OnCompleted();
でストリームの終了ができます。
Subjectでメッセージを配信
全てのストリームは
Subjectが起点だと思って問題無いです。
Subjectでメッセージを配信
IDisposable d =
IObservable<T>.Subscribe<T>(
Action<T> onNext,
Action<Exception> onError,
Action onCompleted
);
onNextのみなど各種パターンが用意されています。
配信されているメッセージを購読
Rxではない実装
private int? previousValue = null;
void Update() {
var value = 監視したい値;
if ( previousValue.HasValue && previousValue.Value != value ) {
/* 処理 */
}
previousValue = value;
}
値の監視
値の監視
Rxでの実装
component.ObserveEveryValueChanged( _ => 監視したい値 )
var rp = new ReactiveProperty<T>(初期値);
があれば
IObservable<T> rpAsObservable { get { return rp; } }
で配信することができます。
配信タイミングは rp.Value = 値; などで値が書き換わった時。
ReactiveProperty<T>
var rp = new ReactiveProperty<T>(初期値);
また、ストリームとして以外でも
rp.Value でその時点での値が取得できます。
ReactiveProperty<T>
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>
ピンと来ない方はExcelなどのセルを
想像して頂けるとわかりやすいかと思います。
そのセルを更新すると他のセルも更新される、という感じです。
ReactiveProperty<T>
その他Bindingもどきなど活用法が多々ありますので
いろいろ調べて使ってみてください。
MV(R)P : Model View ReactiveProperty
という構造も推奨されています。
今回は割愛します。
ReactiveProperty<T>
ReactiveProperty<T>をSerializeFieldに指定しても
ジェネリック型であるため、Inspectorに表示されない。
しかし、ジェネリック型でなくせばその制限がなくなるため、
以下のように基本的な型が用意されている。
IntReactiveProperty LongReactiveProperty ByteReactiveProperty
FloatReactiveProperty DoubleReactiveProperty StringReactiveProperty
BoolReactiveProperty Vector2ReactiveProperty Vector3ReactiveProperty
Vector4ReactiveProperty ColorReactiveProperty RectReactiveProperty
AnimationCurveReactiveProperty BoundsReactiveProperty
QuaternionReactiveProperty
.*ReactiveProperty
List及びDictinaryのReactiveProperty版です。
ReactiveCollection/ReactiveDictionary
AddTo()でちらっと解説しましたが、
IDisposableをまとめて管理してくれるクラスです。
基本はGCされた時にDisposeする用途が多いですが、
Disposeを明示的にコールしたい時などに使用します。
繰り返し使用したい場合はDisposeではなく
Clearを使用するようにしましょう。
同系統のクラスはこちらに解説があります。
http://blog.xin9le.net/entry/2014/02/10/120619
CompositeDisposable
ストリームの再購読の方法として
Repeat()をよく見かけます。
しかし、これだと無限に
購読し続けるおそれがあります。
UniRxの場合は RepeatUntilDestroy() を
使用するようにしましょう。
Repeat()について
Unityではシングルスレッドの動作しかできませんが、
UniRxを使うことで別スレッドで計算などをさせることができます。
(ただし、私は使ったことがないため、紹介だけ・・・)
Observable.Start() : バックグラウンドで処理を実行
ObserveOn(Scheduler.ThreadPool) : 以降の処理を別スレッドで実行
ObserveOnMainThread() : メインスレッドに処理を戻す
別スレッド実行
uGUIやWWWなどのクラスをラップした
オペレータが標準で用意されています。
これにより、以下のような簡単なコードで目的が達成できます。
また、各種オペレータにより、タイムアウトやリトライも簡単に!
(ただし、これも使ったことないです・・・。)
// ボタン押下
Button.onClick.AsObservable().Subscribe()
// httpアクセス
ObservableWWW.Get()
uGUIやhttpなどのラッパー
RxにはHotやColdといった状態があります。
これについては別スライドができるくらいの
情報量がありますので、
解説されたQiitaページの紹介を。
RxのHotとColdについて
http://qiita.com/toRisouP/items/f6088963037bfda658d3
Hot/Cold
SelectやWhereなど、LINQでよく見るオペレータは
ひと通りあるイメージで問題ありません。
その他Rx独自のオペレータについては
以下のサイトなどをご活用ください。
http://rxmarbles.com/
https://msdn.microsoft.com/en-
us/library/system.reactive.linq.observable_methods(v=vs.103).
aspx
http://www.slideshare.net/okazuki0130/reactive-extensionsv01
その他ストリームに対するオペレータ
UniRxの作者様のブログ
株式会社グラニ 河合 宜文 様 @neuecc
http://neue.cc/category/programming/rx
その他
http://blog.xin9le.net/entry/rx-intro
http://qiita.com/toRisouP
その他お勧めな解説サイト
アジェンダ
・(Uni)Rxとは
・Rxの利点と問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
デバッグ方法
Doというオペレータを使用します。
s.Do( x => Debug.Log( x ) )
ストリームの途中の値(到達)を確認する
Finallyというオペレータを使用します。
s.TakeUntil(...)
.Finally( () => Debug.Log( “” ) )
.RepeatUntilDestroy()
Repeatしたのかどうかを確認する
ストリームという性質上できません。
ステップ実行
アジェンダ
・(Uni)Rxとは
・Rxの利点と問題点
・UniRxの導入いろは
・デバッグ方法
・まとめ
まとめ
多分皆さんが
(過去の私も)
思っているほど
難しくないです
なので
ぜひ導入してみてください!
質疑応答
ご静聴
ありがとう
ございました。

Weitere ähnliche Inhalte

Was ist angesagt?

Unityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnity Technologies Japan K.K.
 
Unityでオニオンアーキテクチャ
UnityでオニオンアーキテクチャUnityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャtorisoup
 
【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング
【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング
【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミングUnity Technologies Japan K.K.
 
UniRx完全に理解した
UniRx完全に理解したUniRx完全に理解した
UniRx完全に理解したtorisoup
 
コールバックと戦う話
コールバックと戦う話コールバックと戦う話
コールバックと戦う話torisoup
 
UniTask入門
UniTask入門UniTask入門
UniTask入門torisoup
 
ObserverパターンからはじめるUniRx
ObserverパターンからはじめるUniRx ObserverパターンからはじめるUniRx
ObserverパターンからはじめるUniRx torisoup
 
うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移
うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移
うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移まべ☆てっく運営
 
モバイルアプリにおけるアーティストフレンドリーな水面表現戦略
モバイルアプリにおけるアーティストフレンドリーな水面表現戦略モバイルアプリにおけるアーティストフレンドリーな水面表現戦略
モバイルアプリにおけるアーティストフレンドリーな水面表現戦略Haruki Yano
 
Unityアニメーションシステムの 今と未来の話
Unityアニメーションシステムの 今と未来の話Unityアニメーションシステムの 今と未来の話
Unityアニメーションシステムの 今と未来の話Unity Technologies Japan K.K.
 
【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例
【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例
【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例UnityTechnologiesJapan002
 
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-祐稀 平良
 
UE4のためのより良いゲーム設計を理解しよう!
UE4のためのより良いゲーム設計を理解しよう!UE4のためのより良いゲーム設計を理解しよう!
UE4のためのより良いゲーム設計を理解しよう!Masahiko Nakamura
 
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...エピック・ゲームズ・ジャパン Epic Games Japan
 

Was ist angesagt? (20)

Unityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTips
 
Unityでオニオンアーキテクチャ
UnityでオニオンアーキテクチャUnityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャ
 
【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング
【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング
【CEDEC2018】CPUを使い切れ! Entity Component System(通称ECS) が切り開く新しいプログラミング
 
UniRx完全に理解した
UniRx完全に理解したUniRx完全に理解した
UniRx完全に理解した
 
UniRx の1歩目
UniRx の1歩目UniRx の1歩目
UniRx の1歩目
 
コールバックと戦う話
コールバックと戦う話コールバックと戦う話
コールバックと戦う話
 
UniTask入門
UniTask入門UniTask入門
UniTask入門
 
Riderはいいぞ!
Riderはいいぞ!Riderはいいぞ!
Riderはいいぞ!
 
ObserverパターンからはじめるUniRx
ObserverパターンからはじめるUniRx ObserverパターンからはじめるUniRx
ObserverパターンからはじめるUniRx
 
うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移
うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移
うちではこうやっています UI構築のルールとPlaymakerを使った画面遷移
 
【Unity】Scriptable object 入門と活用例
【Unity】Scriptable object 入門と活用例【Unity】Scriptable object 入門と活用例
【Unity】Scriptable object 入門と活用例
 
モバイルアプリにおけるアーティストフレンドリーな水面表現戦略
モバイルアプリにおけるアーティストフレンドリーな水面表現戦略モバイルアプリにおけるアーティストフレンドリーな水面表現戦略
モバイルアプリにおけるアーティストフレンドリーな水面表現戦略
 
Unityアニメーションシステムの 今と未来の話
Unityアニメーションシステムの 今と未来の話Unityアニメーションシステムの 今と未来の話
Unityアニメーションシステムの 今と未来の話
 
MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTER
MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTERMRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTER
MRTK-Unreal(UX Tools) を利用した HoloLens 2 アプリ開発 | UNREAL FEST EXTREME 2020 WINTER
 
【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例
【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例
【Unite Tokyo 2019】運用中超大規模タイトルにおけるUnityアップデート課題の解決手法と事例
 
UE4とUnrealC++について
UE4とUnrealC++についてUE4とUnrealC++について
UE4とUnrealC++について
 
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
SceneCapture2Dを使って壁の向こうを見る -気になるあの娘の部屋の壁-
 
UE4のためのより良いゲーム設計を理解しよう!
UE4のためのより良いゲーム設計を理解しよう!UE4のためのより良いゲーム設計を理解しよう!
UE4のためのより良いゲーム設計を理解しよう!
 
Unreal Engine 4.27 ノンゲーム向け新機能まとめ
Unreal Engine 4.27 ノンゲーム向け新機能まとめUnreal Engine 4.27 ノンゲーム向け新機能まとめ
Unreal Engine 4.27 ノンゲーム向け新機能まとめ
 
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
 

Ähnlich wie UniRxことはじめ

デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくる
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくるデジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくる
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくるAtsushi Tadokoro
 
メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション
メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーションメディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション
メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーションAtsushi Tadokoro
 
Java初心者勉強会(2015/08/07)資料
Java初心者勉強会(2015/08/07)資料Java初心者勉強会(2015/08/07)資料
Java初心者勉強会(2015/08/07)資料Toshio Ehara
 
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLMedia Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLAtsushi Tadokoro
 
Leap Motion - 1st Review
Leap Motion - 1st ReviewLeap Motion - 1st Review
Leap Motion - 1st ReviewTsukasa Sugiura
 
板ポリだけで めちゃカッコいい グラフィックスを出す!
板ポリだけで めちゃカッコいい グラフィックスを出す!板ポリだけで めちゃカッコいい グラフィックスを出す!
板ポリだけで めちゃカッコいい グラフィックスを出す!notargs
 
Boost9 session
Boost9 sessionBoost9 session
Boost9 sessionfreedom404
 
UnityとBlenderハンズオン第2章
UnityとBlenderハンズオン第2章UnityとBlenderハンズオン第2章
UnityとBlenderハンズオン第2章yaju88
 
Unit testing JavaScript with JUnit/JavaFX
Unit testing JavaScript with JUnit/JavaFXUnit testing JavaScript with JUnit/JavaFX
Unit testing JavaScript with JUnit/JavaFXShinya Mochida
 
この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015
この辺でXamarin導入による 効果と限界をしっかり把握してみよう  MVP Community Camp 2015 この辺でXamarin導入による 効果と限界をしっかり把握してみよう  MVP Community Camp 2015
この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015 Shinichi Hirauchi
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.ContextAkira Takahashi
 
Implementation patterns
Implementation patternsImplementation patterns
Implementation patternsTatsuya Maki
 
Why Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriWhy Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriYuta Okamoto
 

Ähnlich wie UniRxことはじめ (20)

タイマー
タイマータイマー
タイマー
 
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくる
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくるデジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくる
デジタルアートセミナー#2 openFrameworksで学ぶ、 クリエイティブ・コーディング Session 2: 構造をつくる
 
メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション
メディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーションメディア・アートII  第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション
メディア・アートII 第2回 openFrameworks基礎 配列、くりかえし、乱数 ベクトルを使用したアニメーション
 
コルーチンの使い方
コルーチンの使い方コルーチンの使い方
コルーチンの使い方
 
Java初心者勉強会(2015/08/07)資料
Java初心者勉強会(2015/08/07)資料Java初心者勉強会(2015/08/07)資料
Java初心者勉強会(2015/08/07)資料
 
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLMedia Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
 
About Jobs
About JobsAbout Jobs
About Jobs
 
Leap Motion - 1st Review
Leap Motion - 1st ReviewLeap Motion - 1st Review
Leap Motion - 1st Review
 
板ポリだけで めちゃカッコいい グラフィックスを出す!
板ポリだけで めちゃカッコいい グラフィックスを出す!板ポリだけで めちゃカッコいい グラフィックスを出す!
板ポリだけで めちゃカッコいい グラフィックスを出す!
 
Boost9 session
Boost9 sessionBoost9 session
Boost9 session
 
UnityとBlenderハンズオン第2章
UnityとBlenderハンズオン第2章UnityとBlenderハンズオン第2章
UnityとBlenderハンズオン第2章
 
Unit testing JavaScript with JUnit/JavaFX
Unit testing JavaScript with JUnit/JavaFXUnit testing JavaScript with JUnit/JavaFX
Unit testing JavaScript with JUnit/JavaFX
 
react勉強会 #4
react勉強会 #4react勉強会 #4
react勉強会 #4
 
この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015
この辺でXamarin導入による 効果と限界をしっかり把握してみよう  MVP Community Camp 2015 この辺でXamarin導入による 効果と限界をしっかり把握してみよう  MVP Community Camp 2015
この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015
 
Continuation with Boost.Context
Continuation with Boost.ContextContinuation with Boost.Context
Continuation with Boost.Context
 
Arctic.js
Arctic.jsArctic.js
Arctic.js
 
Implementation patterns
Implementation patternsImplementation patterns
Implementation patterns
 
Android gameprogramming
Android gameprogrammingAndroid gameprogramming
Android gameprogramming
 
enchant.js勉強会
enchant.js勉強会enchant.js勉強会
enchant.js勉強会
 
Why Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriWhy Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuri
 

UniRxことはじめ

Hinweis der Redaktion

  1. ご覧のように様々な言語でサポートされています
  2. マウスの状態を取得して、カウントアップ
  3. メッセージストリームを取得 Unitについては次のページ
  4. コメントアウト部分に先ほどまでの処理が入ります。 これだけの追加実装が必要です。
  5. Delayというオペレータだけで実現可能です。
  6. Subjectというものがありますが、 これはメッセージを流すものです。 詳しくは後で説明するので 一旦そういうものとして認識しておいてください。
  7. 1,2,3,4と流した時に2だけが出力されるかとおもいきや・・・
  8. 関数型云々については
  9. 関数型云々については
  10. 関数型云々については宗教戦争になるので 納得出来ない方は流していただけるとありがたいです。
  11. ここでは細かい構文については触れません。 細かい構文については別途ググってください。
  12. Rx以外でも使えます。