UniRx入門①(ReactivePropertyを触ってみよう)

# はじめに
  私がUniRxを勉強し始めた際にobserver、非同期処理、メモリー、イベント駆動など理解できずに挫折したため(今も理解していませんが)、実際にプログラミングをしながら学べるようにしたいと思いこの記事を書きました。しかし、unity全く触ったことが無い人はかなり難しいと思います。

# UniRxの特徴
- 非同期な処理が可能
    - 関数の実行した際に終了を待たずに別の処理を実行できる

 * イベント処理が可能
     - 特定の条件(敵が死んだなど)のタイミングにおいて、処理を別のプログラムに渡すことができる
     
# UniRxの導入
下記の方法以外にも、AssetStoreで導入することもできます。そちらの方が簡単です。
#### 1. UniRxのgithubリポジトリにアクセス
https://github.com/neuecc/UniRx

#### 2. README.md をクリック

#### 3.UPM PackageにあるURLをコピーする
 <img width="500" alt="UPM package" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762332/1be1e950-4687-1b38-7f99-f872a60b4a07.png">
 
#### 4. Unityを開く(unityプロジェクトを作成)

#### 5. UniRxをインストール
　 1. Windowをクリック
　 2. PackageManagerをクリック
　 3. 「+」をクリック
　 4. Add package from git URL...をクリック
　 5. 先ほどのULRをペースト
https://github.com/neuecc/UniRx.git?path=Assets/Plugins/UniRx/Scripts
　 6. Addをクリック

<img width="500" alt="packageManager" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762332/c044f18f-ef77-f9ed-01ce-3deb849eeff0.png">

以上でUniRXの導入は完了です。

# ReactivePropertyを使ってみよう
### ReacivePropertyとは
文字(string)や数字(int, float など)が変更された際に処理を実行します。
今回はスペースキーを押した回数を画面に表示します。

1. SpaceSystemとSpacePresenterというプログラムを作成する
2. SpaceSystemとSpacePresenterという空オブジェクトを作成する
3. プログラムをそれぞれアタッチする
4. TextMeshProを追加する

<img width = "350" alt = "Hierarchy" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762332/9ec9293d-7437-74b4-c581-f7a441d27587.png">

<img width = "300" alt = "inspector" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762332/27a506b2-6093-64b8-cb38-f797ae31c115.png">

---
SpaceSystemはスペースキーを押したかどうかを調べるプログラム、
SpacePresenterはテキストを変更するプログラムです。

~~~c#:SpaceSystem.cs
using UniRx;
using UnityEngine;

public class SpaceSystem : MonoBehaviour
{
    //ReactiveProperty<型(int, float,stringなど)を宣言>
    //今回は回数を数えたいのでint型
    //new ReactiveProperty<int>(),にある()に初期値を代入できる(今回は初期値0を代入)。
    public ReactiveProperty<int> spaceCount = new ReactiveProperty<int>(0);

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            //ReactivePropertyを使う際には変数名.Value(_spaceCount.Value)を用いる
            spaceCount.Value++;
        }
    }
}
~~~
~~~c#:SpacePresenter.cs
using TMPro;
using UniRx;
using UnityEngine;

public class SpacePresenter : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI spaceCountText;
    [SerializeField] private SpaceSystem spaceSystem;

    private void Start()
    {
        //SpaceSystemのSpaceCountの数字が変化した時にSubscribe以下(textの変更)を実装する。
        spaceSystem.spaceCount.Subscribe(x => spaceCountText.text = $"{x}Click").AddTo(this);
    }
}
~~~
その後、SpacePresenterにTextとSpaceSystemをアタッチします。
クリックするたびにTextのカウントが増えば成功です。

---
## ReacitvePropertyの仕組み
　従来の実装だと、クリックを検知した後、SpaceSystemがSpacePresenterをGetComponentし、Textを変更する関数を実行するという流れで実装していたと思います。一方、UniRxを使うとクリックを検知し、SpaceSystemの値が変更されたと同時にSpacePresenterにあるTextを変更する関数が実行されます。
~~~plantuml
@startuml
package 従来の実装{
circle click
class SpaceSystem
class SpacePresenter


click -right-> SpaceSystem 
note left on link
 1.クリックを検知 
end note
SpaceSystem -right-> SpacePresenter
note top on link
 2.SpacePrenterにある
 関数を呼び出す。
end note

}

package UniRxの実装{
circle click
class SpaceSystem
class SpacePresenter

click -right-> SpaceSystem
note left on link
 2.クリックを検知 
end note
SpacePresenter -left-> SpaceSystem
note top on link
 1.SpaceSystemの
 ReacivePropertyを監視
end note
note as note1
 3.SpaceSystemのReactivePropertyが
 変更した際に関数を実行する。
end note

note1 -[hidden]up- SpacePresenter
}

従来の実装 -[hidden]down- UniRxの実装
@enduml
~~~

条件を満たした際にイベントを発行するオブジェクトを(今回だとSpaceSystem)をSubjectと言います。一方、イベントの発生を監視するオブジェクトを(今回だとSpacePresenter)をObserverと言います。
# 最後に
　UniRxは最初使いにくいと感じるかもしれませんが、使えるようになるととても便利なので、頑張ってください。余談ですが、一応ReactivePropertyはSubject機能の含まれている変数らしいので、厳密には違うそうです。

[次回記事]
[UniRx入門②(IReadOnlyReactivePropertyとLINQ)](https://qiita.com/ken141522/items/53a600f19d4335f35c14)