UniRxの1歩目
株式会社インフィニットループ 佐藤正基
自己紹介
30歳
札幌市出身
2011年 インフィニットループ入社
スマートフォンアプリのクライアント開発を担当
I can use Unity a little.
本日のお話
・ UniRxとは何か
・ UniRxのメリット・デメリット
・ UniRxの使いどころ
・ 一例の紹介
UniRxとは何か
UniRx
 Unityで使えるReactive Extensions(Rx)ライブラリ
UniRxとは何か
UniRxとは何か
Reactive Extensions(Rx)
 Reactive Programmingを実現するためのデザイン、実装ライブラリを指す
 C#以外の言語にもライブラリが存在する
Reactive Programming
 "片方の値の変化に対応して、変化する別の値" を宣言的に記述する考え方
UniRxとは何か
UniRxとは何か
Reactive Programming
 "片方の値の変化に対応して、変化する別の値"
  → Excelのセルと計算式をイメージ
   セルに入力した値によって、別のセルの値が自動で更新される仕組み
UniRxのメリット・デメリット
UniRx導入のメリット
 ・ 宣言的に記述できるため、値更新までのフローを記述しなくて良く、
   余分なコードを読まなくて良い。
 ・ 記述に一定の法則性。
 → メンテナンス性の向上が見込める
UniRxのメリット・デメリット
UniRx導入のメリット
 オペレータを組み合わせて、独自イベントを簡潔に宣言できる。
 → 生産性の向上が見込める
UniRxのメリット・デメリット
UniRxのメリット・デメリット
UniRx導入のデメリット
学習コストが高い
UniRxの使いどころ
Update()内の記述を整理する
 Update()内の手続き的で煩雑な記述を、Awake()やStart()内に       
Observable変換して宣言的に記述できる。
UniRxの使いどころ
UniRxの使いどころ
時間経過によるイベント開始
 コルーチンを使用せずに、時間やフレーム経過後のイベントを記述できる。
UIのイベント定義
 UI操作をトリガーとした、イベント定義が楽にできる。
UniRxの使いどころ
一例の紹介
一例の紹介
時間経過によるイベント開始
一例の紹介:時間経過によるイベント開始
private void Start()
{
StartCoroutine(HogeCoroutine());
}
private IEnumerator HogeCoroutine()
{
while(true)
{
yield return new WaitForSeconds(1);
// 1秒ごとの処理
Debug.Log(“1秒ごとの処理”);
}
}
private void Start()
{
// 1秒ごとの処理
Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(_ => Debug.Log(“1秒ごとの処理”));
}
before after(UniRx使用)
一例の紹介:時間経過によるイベント開始
private void Start()
{
// 1秒ごとの処理
Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(_ => Debug.Log(“1秒ごとの処理”));
}
引数のTimeSpanごとにメッセージを発行するソース。
一例の紹介:時間経過によるイベント開始
private void Start()
{
// 1秒ごとの処理
Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(_ => Debug.Log(“1秒ごとの処理”));
}
メッセージを受け取ったら、引数の処理を実行する。
一例の紹介:時間経過によるイベント開始
private void Start()
{
// 1秒ごとの処理
Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(_ => Debug.Log(“1秒ごとの処理”));
}
出力結果
“1秒ごとの処理”
“1秒ごとの処理”
“1秒ごとの処理”
“1秒ごとの処理”
(以下同じ)
一例の紹介
UIのイベント定義
一例の紹介:UIのイベント定義
before
private void Start()
{
// ボタン押下時処理
button.OnClickAsObservable()
.Subscribe(_ => Debug.Log("ボタン押下時処理"));
}
after(UniRx使用)
private void Start()
{
Button button = gameObject.GetComponent<Button>();
button.onClick.AddListener(TaskOnClick);
}
private void TaskOnClick()
{
Debug.Log("ボタン押下時処理");
}
一例の紹介:UIのイベント定義
private void Start()
{
// ボタン押下時処理
button.OnClickAsObservable()
.Subscribe(_ => Debug.Log("ボタン押下時処理"));
}
ボタン押下時にメッセージを発行するソース。
“ボタン押下時処理”
一例の紹介:UIのイベント定義
出力結果
private void Start()
{
// ボタン押下時処理
button.OnClickAsObservable()
.Subscribe(_ => Debug.Log("ボタン押下時処理"));
}
一例の紹介
ReactiveProperty<T>の利用
一例の紹介:ReactiveProperty<T>の利用
ReactiveProperty<T>
 ReactiveProperty<T> は、変数にSubjectの機能を持たせたもの。
 MV(R)Pパターンを実現できるようにする。
Subject
 メッセージの発行と購読の機能を持つ。
一例の紹介:ReactiveProperty<T>の利用
MV(R)Pパターン
 Model View (Reactive) Presenter の略
 UniRxを使用したデザインパターン
 ModelとViewをPresenterがつなぎ、Reactiveに値の更新ができる。
 ModelとViewはお互いに依存しない。
 PresenterはModelとViewをそれぞれ参照する。
一例の紹介:ReactiveProperty<T>の利用
MV(R)Pパターン
一例の紹介:ReactiveProperty<T>の利用
Model
Presenter
View
ReactiveProperty
値更新の通知
Viewへ反映
Modelへ反映
○○○AsObservable
ユーザ操作の通知
一例の紹介:ReactiveProperty<T>の利用
private void Start()
{
button.OnClickAsObservable()
.Where(_ => !player.IsDead)
.Subscribe(_ => player.CurrentHp.Value --);
player.CurrentHp.SubscribeToText(text);
}
public class Player
{
public IReactiveProperty<int> CurrentHp {get; private set;}
public bool IsDead {get; private set;}
public Player()
{
CurrentHp = new ReactiveProperty<int>(10);
CurrentHp.Where(x => x <= 0)
.Subscribe(_ => IsDead = true);
}
}
Presenter Model
一例の紹介:ReactiveProperty<T>の利用
public class Player
{
public IReactiveProperty<int> CurrentHp {get; private set;}
public bool IsDead {get; private set;}
public Player()
{
CurrentHp = new ReactiveProperty<int>(10);
CurrentHp.Where(x => x <= 0)
.Subscribe(_ => IsDead = true);
}
}
ReactivePropertyを定義
Model
一例の紹介:ReactiveProperty<T>の利用
public class Player
{
public IReactiveProperty<int> CurrentHp {get; private set;}
public bool IsDead {get; private set;}
public Player()
{
CurrentHp = new ReactiveProperty<int>(10);
CurrentHp.Where(x => x <= 0)
.Subscribe(_ => IsDead = true);
}
}
ReactivePropertyは、値が更新された時にメッセージを発行する。
Model
一例の紹介:ReactiveProperty<T>の利用
private void Start()
{
button.OnClickAsObservable()
.Where(_ => !player.IsDead)
.Subscribe(_ => player.CurrentHp.Value --);
player.CurrentHp.SubscribeToText(text);
}
引数がfalseの場合、メッセージをフィルタリングするオペレータ。
Presenter
一例の紹介:ReactiveProperty<T>の利用
private void Start()
{
button.OnClickAsObservable()
.Where(_ => !player.IsDead)
.Subscribe(_ => player.CurrentHp.Value --);
player.CurrentHp.SubscribeToText(text);
}
player.CurrentHpの更新に反応した、UIのTextであるtextの更新処理を宣言。
Presenter
まとめ
・ UnityでRxの概念を取り入れられる
・ 使いどころによって効率良く記述できる
・ メンテナンス性が上がる
  ただし、使いこなすための時間が必要
・ MV(R)PパターンはuGUIと相性が良い
ご清聴いただき、ありがとうございました!

UniRx の1歩目