「Unity/UniRx/値変更検知/ObserveEveryValueChanged配列」の版間の差分
提供: 初心者エンジニアの簡易メモ
(→配列の値変更を検知するObserveEveryValueChangedを、Observable.Createで作成) |
(→2度目以降、Observable.Createを実行してくれない場合) |
||
(同じ利用者による、間の9版が非表示) | |||
行1: | 行1: | ||
+ | ==試したこと== | ||
+ | * ObserveEveryValueChangedを配列で検知できる?→NG | ||
+ | * 配列内の値変更を検知するObserveEveryValueChangedを、Observable.Createで作成→OK | ||
+ | * Subjectを使った配列内のキーを検知→OK | ||
+ | * EveryUpdateを使った配列内のデータを検知→NG | ||
+ | |||
==ObserveEveryValueChangedを配列で検知できる?== | ==ObserveEveryValueChangedを配列で検知できる?== | ||
− | + | ObserveEveryValueChangedに配列をそのまま入れるだけだと、値変更を検知できなかった。 | |
==配列内の値変更を検知するObserveEveryValueChangedを、Observable.Createで作成== | ==配列内の値変更を検知するObserveEveryValueChangedを、Observable.Createで作成== | ||
行78: | 行84: | ||
参考:http://wp.nonip.net/archives/2740 | 参考:http://wp.nonip.net/archives/2740 | ||
− | == | + | ===2度目以降、Observable.Create<int>を実行してくれない場合=== |
+ | <pre> | ||
+ | IObservable<int> isCompletedsAsObservable; | ||
+ | isCompletedsAsObservable = Observable.Create<int>(observer => | ||
+ | { | ||
+ | int i = 0; | ||
+ | foreach (RequestData requestData in requestDatas) | ||
+ | { | ||
+ | int id = i; | ||
+ | requestData.ObserveEveryValueChanged(_ => _.IsCompleted) | ||
+ | .Subscribe(isCompleted => | ||
+ | { | ||
+ | observer.OnNext(id); | ||
+ | }); | ||
+ | i++; | ||
+ | } | ||
+ | return Disposable.Empty; | ||
+ | }); | ||
+ | </pre> | ||
+ | の部分を | ||
+ | <pre> | ||
+ | Subject<int> isCompletedsAsObservable; | ||
+ | isCompletedsAsObservable = new Subject<int>(); | ||
+ | int i = 0; | ||
+ | foreach (RequestData requestData in requestDatas) | ||
+ | { | ||
+ | int id = i; | ||
+ | requestData.ObserveEveryValueChanged(_ => _.IsCompleted) | ||
+ | .Subscribe(isCompleted => | ||
+ | { | ||
+ | isCompletedsAsObservable.OnNext(id); | ||
+ | }); | ||
+ | i++; | ||
+ | } | ||
+ | </pre> | ||
+ | な感じで置き換えればよい。 | ||
+ | |||
+ | isCompletedsAsObservable.OnNext(id);の部分が実行されないときは、 | ||
+ | isCompletedsAsObservable.Subscribe()が、OnNextより先に定義されてるか確認する。 | ||
+ | |||
+ | ==Subjectを使った配列内のキーを検知== | ||
<pre> | <pre> | ||
using System.Collections; | using System.Collections; | ||
行123: | 行169: | ||
</pre> | </pre> | ||
− | ==EveryUpdateを使った配列内のデータを検知 | + | ==EveryUpdateを使った配列内のデータを検知== |
毎フレームごとに処理されるので危険かも。 | 毎フレームごとに処理されるので危険かも。 | ||
<pre> | <pre> |
2023年8月26日 (土) 09:43時点における最新版
目次
試したこと
- ObserveEveryValueChangedを配列で検知できる?→NG
- 配列内の値変更を検知するObserveEveryValueChangedを、Observable.Createで作成→OK
- Subjectを使った配列内のキーを検知→OK
- EveryUpdateを使った配列内のデータを検知→NG
ObserveEveryValueChangedを配列で検知できる?
ObserveEveryValueChangedに配列をそのまま入れるだけだと、値変更を検知できなかった。
配列内の値変更を検知するObserveEveryValueChangedを、Observable.Createで作成
配列内のIsCompletedがtrueになったらイベント発生するように。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UniRx; using System; public class ChangeValueListObservableScene : MonoBehaviour { class RequestData { public string Url; public bool IsCompleted; } class SampleClient { IObservable<int> isCompletedsAsObservable; public IObservable<int> IsCompletedsAsObservable { get => isCompletedsAsObservable; set => isCompletedsAsObservable = value; } List<RequestData> requestDatas; public List<RequestData> RequestDatas { get => requestDatas; set => requestDatas = value; } public SampleClient() { requestDatas = new List<RequestData>(); requestDatas.Add(new RequestData { Url = "ttp://example.com", IsCompleted = false, }); requestDatas.Add(new RequestData { Url = "ttp://example2.com", IsCompleted = false, }); isCompletedsAsObservable = Observable.Create<int>(observer => { int i = 0; foreach (RequestData requestData in requestDatas) { int id = i; requestData.ObserveEveryValueChanged(_ => _.IsCompleted) .Subscribe(isCompleted => { observer.OnNext(id); }); i++; } return Disposable.Empty; }); } public void Response(int id) { requestDatas[id].IsCompleted = true; } } void Start() { int id = 1; var sampleClient = new SampleClient(); sampleClient.IsCompletedsAsObservable .Subscribe(id => { if (!sampleClient.RequestDatas[id].IsCompleted) return; Debug.Log("Id=" + id + " Url=" + sampleClient.RequestDatas[id].Url + " IsCompleted=" + sampleClient.RequestDatas[id].IsCompleted); }) .AddTo(gameObject); // 5秒後に遅延実行 Observable.Timer(System.TimeSpan.FromSeconds(5)) .Subscribe(_ => { sampleClient.Response(id); }).AddTo(gameObject); } }
参考:http://wp.nonip.net/archives/2740
2度目以降、Observable.Create<int>を実行してくれない場合
IObservable<int> isCompletedsAsObservable; isCompletedsAsObservable = Observable.Create<int>(observer => { int i = 0; foreach (RequestData requestData in requestDatas) { int id = i; requestData.ObserveEveryValueChanged(_ => _.IsCompleted) .Subscribe(isCompleted => { observer.OnNext(id); }); i++; } return Disposable.Empty; });
の部分を
Subject<int> isCompletedsAsObservable; isCompletedsAsObservable = new Subject<int>(); int i = 0; foreach (RequestData requestData in requestDatas) { int id = i; requestData.ObserveEveryValueChanged(_ => _.IsCompleted) .Subscribe(isCompleted => { isCompletedsAsObservable.OnNext(id); }); i++; }
な感じで置き換えればよい。
isCompletedsAsObservable.OnNext(id);の部分が実行されないときは、 isCompletedsAsObservable.Subscribe()が、OnNextより先に定義されてるか確認する。
Subjectを使った配列内のキーを検知
using System.Collections; using System.Collections.Generic; using UnityEngine; using UniRx; using System; public class ChangeValueListSubjectScene : MonoBehaviour { class SampleClient { public List<string> Urls = new List<string>(); Subject<int> isCompletedsAsObservable; public IObservable<int> IsCompletedsAsObservable { get => isCompletedsAsObservable; } public SampleClient() { Urls.Add("ttp://example.com"); Urls.Add("ttp://example2.com"); isCompletedsAsObservable = new Subject<int>(); } public void Response(int id) { isCompletedsAsObservable.OnNext(id); } } void Start() { int id = 1; var sampleClient = new SampleClient(); sampleClient.IsCompletedsAsObservable .Subscribe(id => { Debug.Log("Id=" + id + " sampleClient.Url=" + sampleClient.Urls[id]); }) .AddTo(gameObject); // 5秒後に遅延実行 Observable.Timer(System.TimeSpan.FromSeconds(5)) .Subscribe(_ => { sampleClient.Response(id); }).AddTo(gameObject); } }
EveryUpdateを使った配列内のデータを検知
毎フレームごとに処理されるので危険かも。
public class ChangeValueListScene : MonoBehaviour { class SampleClient { public List<string> Urls = new List<string>(); public List<bool> IsCompleteds = new List<bool>(); public SampleClient() { Urls.Add("ttp://example.com"); Urls.Add("ttp://example2.com"); IsCompleteds.Add(false); IsCompleteds.Add(false); } public void Response(int id) { IsCompleteds[id] = true; } } void Start() { int id = 0; var sampleClient = new SampleClient(); // 毎フレームごとに処理されるので危険かも。 var observable = Observable.EveryUpdate() .Subscribe(_ => { Debug.Log("IsCompleteds.Count=" + sampleClient.IsCompleteds.Count); int cnt = sampleClient.IsCompleteds.Count; for (int tmpId = 0; tmpId < cnt; tmpId++) { if (!sampleClient.IsCompleteds[tmpId]) continue; Debug.Log("Id=" + tmpId + " sampleClient.Url=" + sampleClient.Urls[tmpId]); sampleClient.IsCompleteds[tmpId] = false; // そのままにすると、連続してここが処理されるので、初期化 } }) .AddTo(gameObject); // 5秒後に遅延実行 Observable.Timer(System.TimeSpan.FromSeconds(5)) .Subscribe(_ => { sampleClient.Response(id); }).AddTo(gameObject); } }