2. 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
4. 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);
}
5. 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-catch
try
{
yield return StartCoroutine(GetGoogle());
}
catch
{
}
}
It cause operation can’t separate.
We have to write on one IEnumerator.
6. Or Callback
IEnumerator 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)
7. 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
8. 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.
10. 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)
11. Gartner’s Hype Cycle
2013 Application Architecture/Application Development
On the Rise - Reactive Programming
12. 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
13. 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
15. UnityAsync with Rx
// x completed then go y and completed z, async flow by LINQ Query Expression
var 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());
16. etc, etc....
// Parallel run A and B
var query = Observable.Zip(
ObservableWWW.Get("http://google.co.jp/"),
ObservableWWW.Get("http://bing.com/"),
(google, bing) => new { google, bing });
// Retry on error
var 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 value
cancel.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
18. 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 Zip
heavyMethod1.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
21. 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
23. Extra methods only for Unity
// Observable.EveryUpdate/FixedUpdate
// produce value on every frame
Observable.EveryUpdate()
.Subscribe(_ => Debug.Log(DateTime.Now.ToString()));
// ObservableMonoBehaviour
public class Hoge : ObservableMonoBehaviour
{
public override void Awake()
{
// All MessageEvent are IObservable<T>
var query = this.OnMouseDownAsObservable()
.SelectMany(_ => this.OnMouseDragAsObservable())
.TakeUntil(this.OnMouseUpAsObservable());
}
}
24. Unity用の各支援メソッド
// prepare container
public 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 callback
UnityEngine.Application.RegisterLogCallback((condition, stackTrace, type) =>
{
subject.OnNext(new LogCallback { Condition = condition, StackTrace = stackTrace, LogType = ty
});
}
return subject.AsObservable();
}
}
Convert Unity Callback to IObservable<T>
25. Unity用の各支援メソッド
// prepare container
public 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 callback
UnityEngine.Application.RegisterLogCallback((condition, stackTrace, type) =>
{
subject.OnNext(new LogCallback { Condition = condition, StackTrace = stackTrace, LogType = ty
});
}
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();
27. 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