
ãã®èšäºã§ã¯ãUnityã䜿çšããŠãã«ãã¹ã¬ããã¢ãã€ã«ã²ãŒã ãéçºããéã«çºçããäž»ãªåé¡ãšã
UniRx ïŒUnityã®ãªã¢ã¯ãã£ãæ¡åŒµïŒã䜿çšããŠãããã解決ããæ¹æ³ã«ã€ããŠèª¬æããŸãã
ãã®èšäºã¯2ã€ã®éšåã§æ§æãããŠããŸãã 1ã€ç®ã¯ãæå°ãã®ãã«ãã¹ã¬ããã«ç¹åããŠãããã¢ã¯ã»ã¹å¯èœãªèšèªã§ã¹ã¬ãããšã¹ã¬ããã®äœææ¹æ³ãã¹ã¬ããã®åæã«ã€ããŠèª¬æããŠããŸãã 2çªç®ã®éšåã¯ããªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ããã®é
眮ãåäœåçãããã³é©ç𿹿³ã«å°å¿µããŸãã
Unityã§ã¹ã¯ãªãããèšè¿°ããããã®èšèªã®1ã€ã¯ã¢ããªã±ãŒã·ã§ã³ãéçºããCïŒã§ããããããã¹ãŠã®ã³ãŒãã¯ãã®äžã§ã®ã¿èšè¿°ãããŸãã ãã«ãã¹ã¬ããããã³ãªã¢ã¯ãã£ãæ¡åŒµã®ååãæ·±ãçè§£ããã«ã¯ããã«ãã¹ã¬ããã®
åºæ¬ãš
ãªã¢ã¯ãã£ãæ¡åŒµãšã¯
äœããèªãããšããå§ãããŸãã èªè
ããã®ãããã¯ã«ç²ŸéããŠããå Žåãæåã®ã»ã¯ã·ã§ã³ã¯ã¹ãããã§ããŸãã
æå°ã®ãã«ãã¹ã¬ãã
ãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã¯ãè€æ°ã®ã¿ã¹ã¯ãå¥ã
ã®ã¹ã¬ããã§åæã«å®è¡ããã¢ããªã±ãŒã·ã§ã³ã§ãã ãã«ãã¹ã¬ããã䜿çšããã¢ããªã±ãŒã·ã§ã³ã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãã¢ã¯ãã£ãã®ãŸãŸã§ããããããŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ã«ããè¿
éã«å¿çããŸãããéäžçãªããã»ããµãŒäœæ¥ãå¿
èŠãšããã¿ã¹ã¯ã¯ä»ã®ã¹ã¬ããã§å®è¡ãããŸãã Monoã䜿çšããCïŒãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã¯ãããŒã¯ãŒãThreadãThreadPoolãããã³éåæããªã²ãŒãã䜿çšããŠéçºãããŸãã
æ§æäŸã䜿çšããŠããã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ãèŠãŠã¿ãŸãããã ååŽåè
ãä»ã®åŽåè
ãšåæã«ãã®è·åãéè¡ãããšä»®å®ããŸãã ããšãã°ã1ã€ã¯åºãæŽãããã1ã€ã¯çªãæŽããŸãã ïŒãããŠãããã¯ãã¹ãŠåæã«èµ·ãããŸãïŒã ãããã¯ç§ãã¡ã®æµãã§ãã

ã¹ã¬ãã-æ¢åã®ã¢ããªã±ãŒã·ã§ã³å
ã«æ°ããã¹ã¬ãããäœæã§ããã¯ã©ã¹ã
éåæããªã²ãŒã-åŒã³åºãããã¡ãœãããšåãã·ã°ããã£ã§å®çŸ©ãããããªã²ãŒãã䜿çšããŠãã¡ãœãããéåæçã«åŒã³åºããŸãã éåæã¡ãœããåŒã³åºãã®å ŽåãBeginInvokeã¡ãœããã䜿çšããå¿
èŠããããŸãã ãã®ã¢ãããŒãã§ã¯ãããªã²ãŒãã¯ããŒã«ããã¹ããªãŒã ãååŸãããã®äžã®ã³ãŒããå®è¡ããŸãã
ThreadPool-ããªããžã§ã¯ãããŒã«ããã¿ãŒã³ã®å®è£
ã ãã®æå³ã¯ã广çãªãããŒç®¡ç::äœæãåé€ãäœæ¥ã®å²ãåœãŠã§ãã 建èšã®äŸãã«æ»ããšãThreadPoolã¯å»ºèšçŸå Žã®å»ºèšæ¥è
ã®æ°ã管çããããããã«ã¿ã¹ã¯ãå²ãåœãŠãè·é·ã§ãã

ã¹ã¬ããåæããŒã«
CïŒèšèªã¯ãã¹ã¬ãããåæããããã®ããŒã«ãæäŸããŸãã ãããã®ããŒã«ã¯ãããã¯ããã³ã¢ãã¿ãŒã®åœ¢åŒã§è¡šç€ºãããŸãã ãããã¯ãã³ãŒããããã¯ã®å®è¡ãè€æ°ã®ã¹ã¬ããã«ãã£ãŠåæã«å®è¡ãããªãããã«ããããã«äœ¿çšãããŸãã ãã ããæ³šæç¹ã1ã€ãããŸãã ãããã®ããŒã«ã䜿çšãããšããããããã¯ïŒãããããã¯ã¹ã¬ããïŒã«ã€ãªããå¯èœæ§ããããŸãã ããã¯æ¬¡ã®ããã«çºçããŸããã¹ã¬ããAã¯ã¹ã¬ããBãå¶åŸ¡ãè¿ãã®ãåŸ
ã¡ãã¹ã¬ããBã¯ã¹ã¬ããAããããã¯ãããã³ãŒããå®è¡ããã®ãåŸ
ã¡ãŸãã ãããã£ãŠããã«ãã¹ã¬ãããšã¹ã¬ããã®åæã¯æ³šæããŠäœ¿çšããå¿
èŠããããŸãã
Unityã®Unityã¹ã¬ããã®åé¡
ã·ã³ã°ã«ã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã®éçºæã«çŽé¢ããäž»ãªåé¡ã¯ãã¡ã€ã³ã¹ã¬ããã§ã®è€éãªæäœã«èµ·å ããUIããªãŒãºã§ãã Unityã«ã¯ã¿ã¹ã¯ã䞊ååããã¡ã«ããºã ããããã³ã«ãŒãã³ïŒã³ã«ãŒãã³ïŒã®åœ¢åŒã§è¡šç€ºãããŸããã1ã€ã®ã¹ã¬ããã§åäœããã³ã«ãŒãã³ã§ãéããäœããå®è¡ããå Žå-ããã«ã¡ã¯ãããªãŒãºã ã¡ã€ã³ã¹ã¬ããã§é¢æ°ã®äžŠåå®è¡ã«æºè¶³ããŠããå Žåã¯ãã³ã«ãŒãã³ã䜿çšã§ããŸãã è€éãªããšã¯äœããããŸãã
ãUnityã®ããã¥ã¡ã³ãã§ã¯ããã®ãããã¯ã¯éåžžã«ããã«ããŒãããŠããŸãã ãã ããã³ã«ãŒãã³ã¯Unityã§æ¬¡ã®ããã«åäœããã€ãã¬ãŒã¿ãŒã§ããããšãæãåºããŠãã ããã
- æåã®ã¹ãããã¯ã³ã«ãã³ãç»é²ããããšã§ã
- ããã«ã UpdateãåŒã³åºããã³ã«LateUpdateãåŒã³åºãåã«ãUnityã¯ç»é²ãããŠãããã¹ãŠã®ã³ã«ãŒãã³ãããŒãªã³ã°ããã¡ãœããå
ã«èšè¿°ãããŠããã³ãŒããåŠçããŸãã
é·æã«å ããŠãã³ã«ãŒãã³ã«ã¯æ¬ ç¹ããããŸãã
- æ»ãå€ãååŸã§ããŸãã
private IEnumerator LoadGoogle() { var www = new WWW("http://google.com"); yield return www;
- ãšã©ãŒåŠç
private IEnumerator LoadGoogle() { try { var www = new WWW("http://google.com"); yield return www; } catch { yield return null; } }
- ã³ãŒã«ããã¯ä»ãæŸèæ
private IEnumerator LoadGoogle(Action<string> callback) { var www = new WWW("http://google.com"); yield return www; if (callback != null) { callback(www.text); } }
- ã³ã«ãŒãã³ã§éãã¡ãœãããåŠçããªãã§ãã ãã
void Start() { Debug.Log(string.Format("Thread id in start method = {0}", Thread.CurrentThread.ManagedThreadId)); StartCoroutine(this.HardMethod()); } private IEnumerator HardMethod() { while (true) { Thread.Sleep(1001); Debug.Log(string.Format("Thread id in HardMethod method = {0}", Thread.CurrentThread.ManagedThreadId)); yield return new WaitForEndOfFrame(); } }
åè¿°ã®ããã«ãã³ã«ãŒãã³ã¯ã¡ã€ã³ã¹ã¬ããã§æ©èœããŸãã ãã®ãããéãã¡ãœãããèµ·åããŠããªãŒãºãååŸããŸãã
ãããã®æ¬ ç¹ã®å€ãã¯ããªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ã®å©ããåããŠç°¡åã«è§£æ¶ã§ããŸãããªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ã¯ãå°æ¥ãããã«å€ãã®ç°ãªãæ©èœããããããéçºã容æã«ããŸãã
ãªã¢ã¯ãã£ãæ¡åŒµãšã¯äœã§ããïŒ
ãªã¢ã¯ãã£ãæ¡åŒµæ©èœã¯ãLinqã¹ã¿ã€ã«ã®ã€ãã³ããšéåæåŒã³åºããæäœã§ããã©ã€ãã©ãªã®ã»ããã§ãã ãã®ãããªæ¡åŒµæ©èœã®ç®æšã¯ãéåæã®çžäºäœçšãçŸããã³ãŒãã®èšè¿°ãåçŽåããããšã§ãã Unityã¯ãåºæ¬çãªãªã¢ã¯ãã£ãæ¡åŒµæ©èœãæäŸããUniRxã©ã€ãã©ãªã䜿çšããŸãã UniRx-.NET Reactive Extensionsã«åºã¥ãUnityã®ãªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ã®å®è£
ã ãªããã®ãã€ãã£ãå®è£
ã䜿çšã§ããªãã®ã§ããïŒ Unityã®æšæºRXãæ©èœããªãããã§ãã ã©ã€ãã©ãªã¯ã¯ãã¹ãã©ãããã©ãŒã ã§ãããPC / Mac / Android / iOS / WP8 / WindowsStoreãã©ãããã©ãŒã ã§ãµããŒããããŠããŸãã
UniRxã¯äœãæäŸããŸããïŒ
- ãã«ãã¹ã¬ãã
- LINQã®ãããªã¡ãœãã
- ç°¡çŽ åãããéåæçžäºäœçšæ§æ
- ã¯ãã¹ãã©ãããã©ãŒã
ã©ã®ããã«æ©èœããŸããïŒ
ãªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ã®ã³ã¢ã¯ã
IObserver
ããã³ IObservable
ã§ãã ãããã¯ããªãã¶ãŒããŒèšèšãã¿ãŒã³ãšããŠãç¥ãããããã·ã¥éç¥ã®äžè¬çãªã¡ã«ããºã ãæäŸããŸãã
- IObservableã€ã³ã¿ãŒãã§ã€ã¹ã¯ãéç¥ïŒãããã€ããŒïŒãéä¿¡ããã¯ã©ã¹ã衚ããŸãã
IObserverã€ã³ã¿ãŒãã§ãŒã¹ã¯ãããããåãåãã¯ã©ã¹ïŒãªãã¶ãŒããŒïŒã衚ããŸãã
Tã¯ãéç¥çšã®æ
å ±ãæäŸããã¯ã©ã¹ã衚ããŸãã
IObserverå®è£
ã¯ãã€ã³ã¹ã¿ã³ã¹ãIObservable.Subscribe
ãããã€ããŒIObservable.Subscribe
æž¡ãããšã«ããããããã€ããŒïŒIObservableå®è£
ïŒããéç¥ãåä¿¡ããæºåãããŸãã ãã®ã¡ãœãã㯠ããããã€ããŒãéç¥ã®éä¿¡ãå®äºããåã«ãªãã¶ãŒããŒã®ç»é²ãè§£é€ããããã«äœ¿çšã§ããIDisposableãè¿ããŸã ã
IObserverã€ã³ã¿ãŒãã§ã€ã¹ã¯ããªãã¶ãŒããŒãå®è£
ããå¿
èŠãããæ¬¡ã®3ã€ã®ã¡ãœãããå®çŸ©ããŸãã
- OnNextã¡ãœãããéåžžããªãã¶ãŒããŒã«æ°ããããŒã¿ãŸãã¯ã¹ããŒã¿ã¹æ
å ±ãæäŸããããã«ãããã€ããŒã«ãã£ãŠåŒã³åºãããŸãã
- OnErrorã¡ãœãããéåžžããããã€ããŒã«ãã£ãŠåŒã³åºãããããŒã¿ã«ã¢ã¯ã»ã¹ã§ããªããç ŽæããŠããããŸãã¯ãããã€ããŒã«ä»ã®ãšã©ãŒãããããšã瀺ããŸãã
- OnCompletedã¡ãœãããéåžžã¯ããªãã¶ãŒããŒãžã®éç¥éä¿¡ã®å®äºã確èªããããã«ãããã€ããŒã«ãã£ãŠåŒã³åºãããŸãã
UniRxã¯ããã«ãã¹ã¬ãããå®è£
ãããã¡ã€ã³ã³ã³ããŒãã³ãã§ããã¹ã±ãžã¥ãŒã©ãå®è£
ããŸãã UniRxã®åºæ¬çãªäžææäœïŒééãã¿ã€ããŒïŒã¯ãMainThreadã䜿çšããŠå®è£
ãããŸãã ããã¯ãã»ãšãã©ã®æäœïŒ Observable.Start
ãé€ãïŒãã¡ã€ã³ã¹ã¬ããã§åäœããããšãæå³ãããã®å Žåãã¹ã¬ããã»ãŒãã¯ç¡èŠã§ããŸãã Observable.Start
ã¯ããã©ã«ãã§ThreadPool Schedulerã䜿çšããŸããã€ãŸããã¹ã¬ãããäœæãããŸãã
åºæ¬æŠå¿µãšçè«çç¥èã«ç²Ÿéããã®ã§ãUniRxã©ã€ãã©ãªã®äœ¿çšäŸãæ€èšããŸãã
ãã®äŸã§ã¯ãUniRxã©ã€ãã©ãªã䜿çšããŠã€ã³ã¿ãŒããããªãœãŒã¹ããããŒã¿ãååŸããããšããŸãã ãªã¢ã¯ãã£ãæ¡åŒµæ©èœã䜿çšããŠããŒã¿ãããŠã³ããŒãããã«ã¯ããªãã¶ãŒããŒãäœæããæšæºã®WWW
Unityã¯ã©ã¹ã®ã©ãããŒã§ããObservableWWW
ã¯ã©ã¹ã䜿çšããå¿
èŠããããŸãã Get
ã¡ãœãã Get
ã³ã«ãŒãã³ã䜿çšãããªãã¶ãŒããŒããµãã¹ã¯ã©ã€ãããIObservableãè¿ããŸãã ãã®ã¢ãããŒãã«ããããUnityã®çµã¿èŸŒã¿ãã«ãã¹ã¬ããã¡ã«ããºã ã®åé¡ãã»ã¯ã·ã§ã³ã§èª¬æããæŸèæãåé¿ãããŸãã
private void Start() { var observer = Observer.Create<string>( x => { Debug.Log("OnNext: " + x); }, ex => Debug.Log("OnError: " + ex.Message), () => Debug.Log("OnCompleted")); ObservableWWW.Get("http://qweqweqwe.qwer.qwer/").Subscribe(observer); }
http://www.nixsolutions.com/ãªã©ã®é©åãªãªã³ã¯ã«ãªã³ã¯ã倿Žãããšã次ã®çµæãåŸãããŸãã
ããã§ã¯ã2ã€ã®Debug.Logsã«ãµã€ã³ã¢ããããŸããã1ã€ç®ã¯OnNext
ã¡ãœãããOnNext
ããããšãã«åžžã«å®è¡ããã2ã€ç®ã¯æ¡ä»¶ã«å¿ããŠã®ã¿ããªã¬ãŒãããŸãã
void Start() { this.subject = new Subject<int>(); this.subject.Subscribe(x => Debug.Log(x)); this.subject.Where(x => x % 2 == 0).Subscribe(x => Debug.Log(string.Format("Hello from {0}", x))); }
ãããã®æ¡åŒµæ©èœã®éèŠãªæ©èœã¯ã EveryUpdate
ã¡ãœããã§ãã Updateã¡ãœããããã³MonoBehaviour
äžäœMonoBehaviour
ããã³ãŒããMonoBehaviour
ã§ããŸãã ããã§ã¯ãããŠã¹ã®ã¯ãªãã¯ããã§ãã¯ããããã¹ãã衚瀺ããŸãã
Observable.EveryUpdate() .Where(x => Input.GetMouseButton(buttonIndex)) .Subscribe(x => Debug.Log(outputString));
ãããã®æ¡åŒµæ©èœã®ãã1ã€ã®è峿·±ãæ©èœã¯ãé
åã®åŠçã§ãã 以äžã«ç€ºãã³ãŒãã¯ãã·ã³ã°ã«ã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ã§å®è¡ããããšã衚瀺ã¹ããªãŒã ãããªãŒãºããŸãã
var arr = Enumerable.Range(0, 5); foreach (var i in arr) { Thread.Sleep(1000); Debug.Log(string.Format("Result = {0}, UtcNow = {1}, ThreadId = {2}", i, DateTime.UtcNow, Thread.CurrentThread.ManagedThreadId)); }
ãã®åé¡ã解決ããã«ã¯ãã¹ã¬ããéã§è² è·ã忣ããThreadPoolã¹ã±ãžã¥ãŒã©ãŒãæç€ºçã«æå®ããŠãUniRxã䜿çšã§ããŸãã
var arr2 = Enumerable.Range(0, 5).ToObservable(Scheduler.ThreadPool); arr2.Subscribe( x => { Thread.Sleep(1000); Debug.Log(string.Format("Result = {0}, UtcNow = {1}, ThreadId = {2}", x, DateTime.UtcNow, Thread.CurrentThread.ManagedThreadId)); });
ãã®ã¢ãããŒãã®è峿·±ãç¹åŸŽã¯ãããªãŒã¹ããªãŒã ãåå埩ã«å²ãåœãŠãããããšã§ãã
ãã®äŸã§ã¯ãã¡ã€ã³ã¹ã¬ããã§å®è¡ããããšã¢ããªã±ãŒã·ã§ã³ãããªãŒãºããè€éãªã¡ãœãããããã€ããããŸãã Rxã䜿çšãããšããã¹ãŠãæ£åžžã«æ©èœããã¡ãœããããæ»ãå€ãååŸããŠåŠçããŸãã
private void Awake() { var heavyMethod = Observable.Start(() => { var timeToSleep = 1000; var returnedValue = 10; Debug.Log(string.Format("Thread = {0} UtcNow = {1}", Thread.CurrentThread.ManagedThreadId, DateTime.UtcNow)); Thread.Sleep(timeToSleep); return returnedValue; }); var heavyMethod2 = Observable.Start(() => { var timeToSleep = 2000; var returnedValue = 20; Debug.Log(string.Format("Thread = {0} UtcNow = {1}", Thread.CurrentThread.ManagedThreadId, DateTime.UtcNow)); Thread.Sleep(timeToSleep); return returnedValue; }); Observable.WhenAll(heavyMethod, heavyMethod2) .ObserveOnMainThread() .Subscribe(result => { Debug.Log(string.Format("Thread = {0}, first result = {1}, second result = {2} UtcNow = {3}", Thread.CurrentThread.ManagedThreadId, result[0], result[1], DateTime.UtcNow)); }); }
å¥ã®åªããã¡ã«ããºã ã¯ãã€ã³ãã£ã³ã°ã§ãã ããã䜿çšãããšãMVPãã¿ãŒã³ãç°¡åã«å®è£
ã§ããŸãã ãã®äŸã§ã¯ãã¢ãã«ã¯Enemyã¯ã©ã¹ã§ãããåå¿ã¯ã©ã¹ãèšè¿°ããŠããŸãã IsDead
ããããã£ã¯CurrentHp
IsDead
äŸåããŸãããŒãæªæºã®å Žåã IsDead
ã¯= trueã«ãªããŸãã
public class Enemy { public Enemy(int initialHp) { this.CurrentHp = new ReactiveProperty<long>(initialHp); this.IsDead = this.CurrentHp.Select(x => x <= 0).ToReactiveProperty(); } public ReactiveProperty<long> CurrentHp { get; private set; } public ReactiveProperty<bool> IsDead { get; private set; } }
ãã¬ãŒã³ã¿ãŒã¯ãã¢ãã«ãšãã£ã¹ãã¬ã€ã®æ¥ç¶ãæ
åœããŸããããã«ãããã¢ãã«ã®åå¿ç¹æ§ããã£ã¹ãã¬ã€ã®ããŒãã«ãã€ã³ãã§ããŸãã MvpExample
ã¯ã©ã¹ã¯ãã¬ãŒã³ã¿ãŒã§ãããã¢ãã«ïŒ Enemy
ã¯ã©ã¹ïŒãšãã£ã¹ãã¬ã€ïŒ Button
ããã³Toggle
ïŒã®äž¡æ¹ãžã®ãªã³ã¯ããããŸãã ãŸãããªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ã®ãããã§ãã³ãŒãã䜿çšããŠããŸããŸãªUIèŠçŽ ã®åäœãèšå®ããããšãã§ããŸãã OnClickAsObservable
ããã³OnValueChangedAsObservable
ã䜿çšããŠãButtonããã³Toggleã®åäœã説æããŸããã
public class MvpExample : MonoBehaviour { private const int EnemyHp = 1000; [SerializeField] private Button myButton; [SerializeField] private Toggle myToggle; [SerializeField] private Text myText; private void Start() { var enemy = new Enemy(EnemyHp); this.myButton.OnClickAsObservable().Subscribe(x => enemy.CurrentHp.Value -= 99);
次ã«ãUIèŠçŽ ã«ãªã¢ã¯ãã£ãããããã£ã远å ããŸããã Enemy
ãCurrentHp
倿Žãããšãããã¹ããèªåçã«å€æŽãããŸãã IsDead
ç¶æ
ãtrue
å€ãããšããã¿ã³ãšToggle
äž¡æ¹ãç¡å¹ã«ãªããŸãã
Unityã§ã¢ããªã±ãŒã·ã§ã³ãéçºãããšãã«ãªã¢ã¯ãã£ããšã¯ã¹ãã³ã·ã§ã³ã䜿çšãããšãå€ãã®å©ç¹ããããŸãã äž»ãªãã®ã¯ããã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®æ§æãç°¡çŽ åããããšã§ãã ã³ã«ãŒãã³ã䜿çšããæŸèæã®æ°ã倧å¹
ã«åæžãããã¢ããªã±ãŒã·ã§ã³ã®æè»æ§ãšé«éæ§ãåäžããŸãã ãŸããUniRxã䜿çšããŠãã«ãã¹ã¬ããã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããå Žåãè€æ°ã®ã¹ããªãŒã ã«ããå€ã®å€æŽããããŒã¿ã®äžéšãä¿è·ããå¿
èŠãããããšã«æ³šæããå¿
èŠããããŸãã
䟿å©ãªãªã³ã¯ïŒ