Upload
yoshifumi-kawai
View
4.223
Download
5
Embed Size (px)
DESCRIPTION
https://github.com/neuecc/UniRx
Citation preview
UniRx - Reactive Extensions for Unity
Yoshifumi Kawai - @neuecc
Self Introduction
@Work
CTO/Director at Grani, Inc
Grani is top social game developer in Japan
C# 5.0 + .NET Framework 4.5 + ASP.NET MVC 5
@Private
Microsoft MVP for Visual C#
Web http://neue.cc/ (JPN)
Twitter @neuecc (JPN)
linq.js - http://linqjs.codeplex.com/ LINQ to Objects for JavaScript
Async in UnityCoroutine is not good practice for asynchronous operation
Async in Unity
Network operation is awaitable by yield return
Good by callback hell!
It’s good! good?
I have never thought it is good.
IEnumerator OnMouseDown(){
var www = new WWW("http://bing.com/");yield return www; // await
Debug.Log(www.text);}
Problem of yield
can’t return result
can’t handle exception
IEnumerator GetGoogle(){
var www = new WWW("http://google.com/");yield return www;
// can’t return www.text}
IEnumerator OnMouseDown(){
// this code is compiler error// yield can’t surround with try-catchtry{
yield return StartCoroutine(GetGoogle());}catch{}
}
It cause operation can’t separate.
We have to write on one IEnumerator.
Or CallbackIEnumerator GetGoogle(Action<string> onCompleted, Action<Exception> onError){
var www = new WWW("http://google.com/");yield return www;
if (!www.error) onError(new Exception(www.error));else onCompleted(www.text);
}
IEnumerator OnMouseDown(){
string result;Exception error;yield return StartCoroutine(GetGoogle(x => result = x, x => error = x));
string result2;Exception error2;yield return StartCoroutine(GetGoogle(x => result2 = x, x => error2 = x));
}
Welcome to the callback hell!
(We can await by yield but terrible yet)
async Task<string> RunAsync(){
try{
var v = await new HttpClient().GetStringAsync("http://google.co.jp/");var v2 = await new HttpClient().GetStringAsync("http://google.co.jp/");return v + v2;
}catch (Exception ex){
Debug.WriteLine(ex);throw;
}}
If so C# 5.0(async/await)
yield(await) can receive return value
We can handle exception by try-catch
Async method can return result
Unity 5.0
Will be released on 2014 fall
But Mono runtime is not renewed
C# is still old(3.0)
async has not come.
IL2CPP - The future of scripting in Unity
http://blogs.unity3d.com/2014/05/20/the-future-of-scripting-in-
unity/
It’s future.
Reactive Programming
About Reactive Programming
Recently attracted architecture style
The Rective Manifesto http://www.reactivemanifesto.org/
Reactive Streams http://www.reactive-streams.org/
Principles of Reactive Programming
https://www.coursera.org/course/reactive
Martin Odersky(Creator of Scala)
Eric Meijer(Creator of Reactive Extensions)
Roland Kuhn(Akka Tech Lead)
Gartner’s Hype Cycle
2013 Application Architecture/Application Development
On the Rise - Reactive Programming
Reactive Extensions
Reactive Programming on .NET
https://rx.codeplex.com
Project of Microsoft, OSS
LINQ to events, asynchronous and more.
Port to other languages
RxJava(by Netflix)
https://github.com/Netflix/RxJava 2070 Stars
RxJS(by Microsoft)
https://github.com/Reactive-Extensions/RxJS 1021 Stars
UniRx - Reactive Extensions for Unity
Why UniRx?
Official Rx is great impl but too heavy, can’t work old C#
and can’t avoid iOS AOT trap.
RxUnity is re-implementation of RxNet for Unity
and several Unity specified utilities(Scheduler, ObservableWWW, etc)
Available Now
GitHub - https://github.com/neuecc/UniRx/
On Unity AssetStore(FREE)
http://u3d.as/content/neuecc/uni-rx-reactive-extensions-for-
unity/7tT
Curing Your Asynchronous Programming BluesRx saves your life & codes
UnityAsync with Rx
// x completed then go y and completed z, async flow by LINQ Query Expressionvar query = from x in ObservableWWW.Get("http://google.co.jp/")
from y in ObservableWWW.Get(x)from z in ObservableWWW.Get(y)select new { x, y, z };
// Subscribe = “finally callback“(can avoid nested callback)query.Subscribe(x => Debug.Log(x), ex => Debug.LogException(ex));
// or convert to Coroutine and await(ToCoroutine is yieldable!)yield return StartCoroutine(query.Do(x => Debug.Log(x)).ToCoroutine());
etc, etc....
// Parallel run A and Bvar query = Observable.Zip(
ObservableWWW.Get("http://google.co.jp/"),ObservableWWW.Get("http://bing.com/"),(google, bing) => new { google, bing });
// Retry on errorvar cancel = ObservableWWW.Get("http://hogehgoe")
.OnErrorRetry((Exception ex) => Debug.LogException(ex),retryCount: 3, delay: TimeSpan.FromSeconds(1))
.Subscribe(Debug.Log);
// Cancel is call Dispose of subscribed valuecancel.Dispose();
// etc, etc, Rx has over 100 operators(methods) for method chain// you can control all execution flow of sync and async
ObservableWWW is included in
RxUnity, it is wrapped WWW, all
method return IObservable
Orchestrate MultiThreadingand LINQ to MonoBehaviour Message Events
UniRx solves MultiThreading problems// heavy work start on other thread(or specified scheduler)var heavyMethod1 = Observable.Start(() =>{
Thread.Sleep(TimeSpan.FromSeconds(1));return 1;
});var heavyMethod2 = Observable.Start(() =>{
Thread.Sleep(TimeSpan.FromSeconds(3));return 2;
});
// Parallel work and concatenate by ZipheavyMethod1.Zip(heavyMethod2, (x, y) => new { x, y })
.ObserveOnMainThread() // return to MainThread
.Subscribe(x =>{
// you can access GameObject(GameObject.Find("myGuiText")).guiText.text = x.ToString();
});
join other thread
ObserveOnMainThread
is return to MainThread
and after flow can access
GameObject
easily cancel(call Dispose
of subscribed value) etc,
many methods supports
multi thread programming
AsyncA AsyncB
SelectMany – linear join
AsyncA
Zip – parallel join
AsyncB
Result
AsyncA AsyncB
AsyncC
Result
AsyncA().SelectMany(a => AsyncB(a)).Zip(AsyncC(), (b, c) => new { b, c });
SelectMany + Zip – Compose Sample
var asyncQuery = from a in AsyncA()from b in AsyncB(a)from c in AsyncC(a, b)select new { a, b, c };
multiplex from(SelectMany)
AsyncA AsyncB AsyncC Result
Extra Gems
Extra methods only for Unity// Observable.EveryUpdate/FixedUpdate// produce value on every frameObservable.EveryUpdate()
.Subscribe(_ => Debug.Log(DateTime.Now.ToString()));
// ObservableMonoBehaviourpublic class Hoge : ObservableMonoBehaviour{
public override void Awake(){
// All MessageEvent are IObservable<T>var query = this.OnMouseDownAsObservable()
.SelectMany(_ => this.OnMouseDragAsObservable())
.TakeUntil(this.OnMouseUpAsObservable());}
}
Unity用の各支援メソッド// prepare containerpublic class LogCallback{
public string Condition;public string StackTrace;public UnityEngine.LogType LogType;
}
public static class LogHelper{
static Subject<LogCallback> subject;
public static IObservable<LogCallback> LogCallbackAsObservable(){
if (subject == null){
subject = new Subject<LogCallback>();
// publish to subject in callbackUnityEngine.Application.RegisterLogCallback((condition, stackTrace, type) =>{
subject.OnNext(new LogCallback { Condition = condition, StackTrace = stackTrace, LogType = type });});
}
return subject.AsObservable();}
}
Convert Unity Callback to IObservable<T>
Unity用の各支援メソッド// prepare containerpublic class LogCallback{
public string Condition;public string StackTrace;public UnityEngine.LogType LogType;
}
public static class LogHelper{
static Subject<LogCallback> subject;
public static IObservable<LogCallback> LogCallbackAsObservable(){
if (subject == null){
subject = new Subject<LogCallback>();
// publish to subject in callbackUnityEngine.Application.RegisterLogCallback((condition, stackTrace, type) =>{
subject.OnNext(new LogCallback { Condition = condition, StackTrace = stackTrace, LogType = type });});
}
return subject.AsObservable();}
}
Convert Unity Callback to IObservable<T>
// It’s separatable, composable, etc.LogHelper.LogCallbackAsObservable()
.Where(x => x.LogType == LogType.Warning)
.Subscribe();
LogHelper.LogCallbackAsObservable().Where(x => x.LogType == LogType.Error).Subscribe();
Conclusion
Conclusion
IEnumerator for Async is bad
and C# 5.0(async/await) hasn’t come
Then UniRx
Why Rx, not Task?
Task is poor function without await
And for MultiThreading, Event Operation, any more
Available Now FREE
GitHub - https://github.com/neuecc/UniRx/
AssetStore – http://u3d.as/content/neuecc/uni-rx-reactive-
extensions-for-unity/7tT