With Unity 2017.1 we have the opportunity to implement async methods. I never worked with them so im asking myself what are the advantages/disadvantages of Coroutines and async methods?
Is one better than the other?
With Unity 2017.1 we have the opportunity to implement async methods. I never worked with them so im asking myself what are the advantages/disadvantages of Coroutines and async methods?
Is one better than the other?
Both fulfil different needs.
Coroutines are useful for executing methods over a number of frames.
Async methods are useful for executing methods after a given task has finished.
e.g. async methods can commonly used to wait for I/O operations to complete.
Coroutines can be used to move an object each frame.
Unity devs have said they may replace Coroutines with an Async/Await style alternative, but they do not currently have any plans to, especially until they is a distinct reason to.
That makes sense. Lets say i want to Destroy a gameobject after 5 seconds. Is it better to use a coroutine or an async method?
@Reeley Probably a coroutine. No faffing about in other threads and the code will likely be cleaner + more readable.
for that use a CoRoutine since it is all on the main thread and you simply want to wait X amount of time.
I havent dealt with the Task, Task, assync and await in unity yet, but i have for other pure .net or xamarin projects. What they are useful for is waiting on a long running task to complete. Such as things like waiting for the response to a REST API request, and than doing something with that response after it is complete, or really dealing with any long running task that does not need to be on the main thread.
When it comes to unity and doing stuff over time, i would stick with coroutines only since that is what they were made for.
Also, just to note, there is no reason to use a coroutine or async to destroy a gameobject as the destroy call already allows you to specify a time.
Seems like I might be missing something here. I just tried to import System.Threading.Tasks and use the async keyword in Unity 2017.1. The namespace didnāt exist, and I got a compiler error āFeature `asynchronous functionsā cannot be used because it is not part of the C# 4.0 language specificationā.
Perhaps this is a not-yet implemented feature?
You may have to change it to C# 4.6 in the Player Settings.
Thanks, that did the trick! Now to go experiment with these cool new features.
I wonder if Unity/someone will do a write-up on the new C# 6 features and examples of where to use them? I assume thereās some reason that they made the switch other than async capabilities. Maybe thereās just inherent optimizations that come along with the new compiler?
async/await doesnāt necessarily have to be for running async stuff:
public void StartTimer()
{
DoSomething(() => Console.WriteLine("Hello!"));
}
public async void DoSomething(Action callback)
{
while (true)
{
await Task.Delay(1000);
callback();
}
}
When used this way, itās pretty similar to coroutines. That said, I believe thereās a bit more overhead than just using coroutines, so YMMV.
Iāve written state machines and states using async/await as I found it pretty handy for those ājust in caseā scenarios where I needed to do async stuff in some state.
Thats exactly what i wonder about, but i guess your right it will have more overhead because a Task has to be created.
There is a library I made.
It makes async/await and coroutine handled easily.
using Asyncoroutine;
async void Awake()
{
await new WaitForSeconds(1f);
Debug.Log("WaitForSeconds");
await Task.Delay(1000);
Debug.Log("Delay");
WWW www = await new WWW("http://google.com");
Debug.Log(www.text);
await new WaitForSecondsRealtime(1f);
Debug.Log("WaitForSecondsRealtime");
await UnityCoroutine();
Debug.Log("UnityCoroutine");
}
https://github.com/zsaladin/asyncoroutine
Note : Itās being still developed so it needs test.
General information that might help. Obviously all IHMO:
o Unity isnāt upgrading C# versions to get any of the new features. Itās just general compatibility and bug-fixes.
o The original command/concept is fork and sleep, which is 30 years old. Unity implemented their version as coroutines; C# is finally adding theirs.
o Microsoft products (C#) generate buzz just because. People will talk up any new feature the way theyāll get excited about new Team Fortress skins.
o Sure, running on another thread can speed things up, but you pay for it with race conditions, and theyāre the worst.
Instead of thinking that Unity is providing us with this new await command, I think of it as the TV cable channels that just came with the package.
I still havenāt managed to use co-routines much, probably too old fashioned. I still drop by these threads to see if thereās anything Iām missing.
For anyone interested, I took a deeper dive into this topic and wrote about my findings here
Enjoyed the write up, thanks. Learned some cool things! Itās good you accounted for Unityās game time as well.
Good stuff! Just a couple niggly points. You mentioned that yielding null in a coroutine does nothing when in actuality it waits a frame. You also mentioned this being part of C# 4.6. This is the version of the runtime, not the language. async/await is a part of C# 6.0 IIRC.
Indeed a good explanation.
To add some notes, the default logger behind Debug.Log is not necessarily throwing exceptions when itās called from other threads.
In regards to the second snippet in āException Handlingā, itās common practice to use the async keyword all the way up anyway.
So this:
private void Start()
{
SomeTask();
}
private async Task SomeTask()
{
...
if ( some boolean expression)
{
throw new System.Exception (" ... ");
}
}
should reallread
private async void Start()
{
/* await */ SomeTask();
}
Thatāll allow the Exception to bubble up correctly.
Or you can now handle it yourself:
private async void Start()
{
try
{
/* await */ SomeTask();
}
catch (Exception exc)
{
// handle
}
}
Edit
The / await */ parts exist because the difference between non-awaiting and awaiting is also significant.