UniRxで配列を扱った時個人的に詰まったとこの解決
また、別にReactivePropertyに限った話ではないので注意。
その1
UniRxでReactivePropertyを使うことはよくあると思う。
で、それを使って配列を扱いたいともちろん思うと思う。
public class RxManager : MonoBehaviour {
public StringReactiveProperty[] data;
}
例えばこれを扱うとする。で、購読側がこんな感じ
やりたいことはdataが変更したらView classにその変更をする通知をする
public class Passenger : MonoBehaviour {
public RxManager manager;
public View view;
void Start(){
//これは失敗する!
for (int i = 0; i < manager.data.Length; i++) {
manager.data[i].Subscribe (x => view.showButton (i,x));
}
}
で、これは失敗する。
view.showButton (i,x)のiが
なぜか常にi = Lengthの値になるのだ
で、早速解決方法
public class Passenger : MonoBehaviour {
public RxManager manager;
public View view;
void Start(){
for (int i = 0; i < manager.data.Length; i++) {
////reactivepropatyで配列を扱う場合、一度変数を受ける
int a = i;
manager.data[a].Subscribe (x => view.showButton (a,x));
}
}
いいたいことはわかる。aもiも同じじゃないのかと。なぜ一回受けるのかと
でもまあちょっと古いC#クエリ式(Subscribe (x =>)でやる場合、こうなのだと思ってほしい。
また、補足であるがViewはこんな感じ
public class View : MonoBehaviour {
public Button[] itembtn;
public Text[] itemtext;
public void showButton(int num,string text){
itemtext [num].text = text;
}
}
これでRxManagerの値を何らかの方法で変化させるだけでそれに応じたボタンのテキストも変更されるというわけ。
ItemMenu画面とかに使えると思う。
その2 CopyTo()
を使うとストリームごとコピーしてしまう。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UniRx;
using UnityEngine.UI;
public class ReactiveCopy: MonoBehaviour {
public IntReactiveProperty[] tesint = new IntReactiveProperty[5];
public IntReactiveProperty[] tesint2 = new IntReactiveProperty[5];
void Start(){
for(int i = 0;i < tesint.Length;i++){
int a = i;
tesint [i].Subscribe (x => tesint2[a].Value = x).AddTo (gameObject);
tesint2 [i].Subscribe (x => Debug.Log ("s" + x));
}
}
//copytoでストリームごとコピーされる。
public void copyint(){
tesint.CopyTo (tesint2, 0);
}
}
これでcopyint関数を後から実行するとtestint[]のストリームがtestint2[]のストリームに上書きされる。
のでこのプログラムだとtestint[]の値を変更するとdebug.logが表示される。
解決法としては一回変数を受けてからなのだろうか、現在検証中。