Top
Best
New

Posted by ingve 3 days ago

Looking at Unity made me understand the point of C++ coroutines(mropert.github.io)
122 points | 113 commentspage 2
pjc50 9 hours ago|
Always jarring to see how Unity is stuck on an ancient version of C#. The use of IEnumerable as a "generator" mechanic is quite a good hack though.
Deukhoofd 8 hours ago||
Thankfully they are actively working towards upgrading, Unity 6.8 (they're currently on 6.4) is supposed to move fully towards CoreCLR, and removing Mono. We'll then finally be able to move to C# 14 (from C# 9, which came out in 2020), as well as use newer .NET functionality.

https://discussions.unity.com/t/coreclr-scripting-and-ecs-st...

pjmlp 7 hours ago|||
For several years now, I wonder if it will ever happen.
Deukhoofd 6 hours ago||
Well, this is at least an update from earlier this month with a clear roadmap of how they're going to get there. There's hope!
Rohansi 8 hours ago|||
One annoying piece of Unity's CoreCLR plan is there is no plan to upgrade IL2CPP (Unity's AOT compiler) to use a better garbage collector. It will continue to use Boehm GC, which is so much worse for games.
pjc50 7 hours ago||
Why wouldn't they use the GC that comes with the dotnet AOT runtime?
pjmlp 7 hours ago|||
Probably because the AOT runtime doesn't run on game consoles, straight out of the box.

Capcom has their own fork of .NET for the Playstation, for example.

I don't know what kind of GC they implemented.

Rohansi 3 hours ago|||
They just haven't announced any plans to do so yet. They might one day.

They will not be using .NET AOT probably ever though. Unity's AOT basically supports full C# (reflection etc) while .NET opted to restrict it and lean more on generated code.

tyleo 9 hours ago|||
Unity is currently on C# 9 and that IEnumerable trick is no longer needed in new codebases. async is properly supported.
debugnik 9 hours ago|||
Not that ancient, they just haven't bothered to update their coroutine mechanism to async/await. The Stride engine does it with their own scheduler, for example.

Edit: Nevermind, they eventually bothered.

Rohansi 8 hours ago|||
It's ancient. The latest version of Unity only partially supports C# 9. We're up to C# 14 now. But that's just the language version. The Mono runtime is only equivalent to .NET Framework 4.8 so all of the standard library improvements since .NET (Core) are missing. Not directly related to age but it's performance is also significantly worse than .NET. And Unity's garbage collector is worse than the default one in Mono.
debugnik 5 hours ago||
The runtime is absolutely ancient, but I think the version number says more about C#'s churn than about how outdated the language version is. Take my opinion on C# with a grain of salt, though, I was an F#-er until the increasing interop pains forced me to drop it.
Rohansi 4 hours ago||
There were also a lot of performance improvements to .NET over the last few years.
nananana9 9 hours ago|||
Unity has async too [1]. It's just that in a rare display of sanity they chose to not deprecate the IEnumerator stuff.

[1] https://docs.unity3d.com/6000.3/Documentation/ScriptReferenc...

debugnik 8 hours ago||
Oh I totally missed this, thanks! I was overly confident they wouldn't have bothered, given how long it was taking. The last time I used Unity was 2022.3, which was apparently the last version without Awaitable.
Philip-J-Fry 8 hours ago|||
>The use of IEnumerable as a "generator" mechanic is quite a good hack though.

Is that a hack? Is that not just exactly what IEnumerable and IEnumerator were built to do?

jayd16 5 hours ago||
It feels hacky because you have to (had to?) use it as the async/await tool and because of that the types you're generating and how they are handled is a huge mess.

Really you're generating the vague concept of a yield instruction but you can return other coroutines that are implicitly run and nest your execution... Because of this you can't wait less than a frame so things are often needlessly complicated and slow.

It's like using a key to jam a door shut. Sure a key is for keeping doors closed but...

ahoka 8 hours ago|||
IIRC generators and co-routines are equivalent in a sense that you can implement one with the other.
Sharlin 7 hours ago||
Generators are a subset of coroutines that only yield data in one direction. Full coroutines can also receive more input from the caller at every yield point.
repelsteeltje 9 hours ago||
Not too different from C++'s iterator interface for generators, I guess.
bradrn 9 hours ago||
In Haskell this technique has been called ‘reinversion of control’: http://blog.sigfpe.com/2011/10/quick-and-dirty-reinversion-o...
FpUser 3 hours ago||
I do not find so called "green threads" useful at all. In my opinion except some very esoteric cases they serve no purpose in "native" languages that have full access to all OS threading and IO facilities. Useful only in "deficient" environments like inherently single threaded request handlers like NodeJS.
maltyxxx 9 hours ago||
[dead]
rando-guy 9 hours ago||
[dead]
momocowcow 8 hours ago|
No serious devs even uses Unity coroutines. Terrible control flow and perf. Fine for small projects on PC.
krajzeg 8 hours ago||
Echoing the thoughts of the only current sibling comment: lots of "serious" developers (way to gatekeep here) definitely use coroutines, when they make sense. As mentioned, it's one of the best ways to have something update each frame for a short period of time, then neatly go away when it's not needed anymore. Very often, the tiny performance hit you take is completely outweighed by the maintanability/convenience.
DonHopkins 8 hours ago||
...and then crash when any object it was using gets deleted while it's still running, like when the game changes scenes, but it becomes a manual, error-prone process to track down and stop all the coroutines holding on to references, that costs much more effort than it saves.

I've been a serious Unity developer for 16 years, and I avoid coroutines like the plague, just like other architectural mistakes like stringly typed SendMessage, or UnityScript.

Unity coroutines are a huge pain in the ass, and a lazy undisciplined way to do things that are easy to do without them, using conventional portable programming techniques that make it possible to prevent edge conditions where things fall through the cracks and get forgotten, where references outlive the objects they depend on ("fire-and-forget" gatling foot-guns).

Coroutines are great -- right up until they aren’t.

They give you "nice linear code" by quietly turning control flow into a distributed state machine you no longer control. Then the object gets destroyed, the coroutine keeps running, and now you’re debugging a null ref 200 frames later in a different scene with an obfuscated call stack and no ownership.

"Just stop your coroutines" sounds good until you realize there’s no coherent ownership model. Who owns it? The MonoBehaviour? The caller? The scene? Every object it has a reference to? The thing it captured three yields ago? The cure is so much worse than the disease.

Meanwhile: No static guarantees about lifetime. No structured cancellation. Hidden allocation/GC from yield instructions. Execution split across frames with implicit state you can’t inspect.

Unity has a wonderful editor that lets you inspect and edit the state of the entire world: EXCEPT FOR COROUTINES! If you put your state into an object instead of local variables in a coroutine, you can actually see the state in the editor.

All of this to avoid writing a small explicit state machine or update loop -- Unity ALREADY has Update and FixedUpdate just for that: use those.

Coroutines aren’t "cleaner" -- they just defer the mess until it’s harder to reason about.

If you can't handle state machines, then you're even less equipped to handle coroutines.

kdheiwns 6 hours ago|||
Never had a crash from that. When the GameObject is destroyed, the coroutine is gone. If you're using a coroutine to manage something outside the scope of the GameObject itself, that's a problem with your own design, not the coroutine itself.

It'd be like complaining about arrays being bad because if you pass a pointer to another object, nuke the original array, then try to access the data, it'll cause an error. That's kind of... your own fault? Got to manage your data better.

Unity's own developers use them for engine code. To claim it's just something for noobs is a bit of an interesting take, since, well, the engine developers are clearly using them and I doubt they're Unity noobs. They made the engine.

Arch485 7 hours ago||||
I dunno, I've worked on some pretty big projects that have used lots of coroutines, and it's pretty easy to avoid all of the footguns.

I'm not advocating for the ubiquitous use of coroutines (there's a time and place), but they're like anything else: if you don't know what you're doing, you'll misuse them and cause problems. If you RTFM and understand how they work, you won't have any issues.

DonHopkins 7 hours ago||
They're a crutch for people who don't know what they're doing, so of course they invite a whole host of problems that are harder to solve than doing it right in the first place.

If you strictly require people to know exactly what they're doing and always RTFM and perfectly understand how everything works, then they already know well enough to avoid coroutines and SendMessage and UnityEvents and other footguns in the first place.

It's much easier and more efficient to avoid all of the footguns when you simply don't use any of the footguns.

bob1029 7 hours ago|||
> Who owns it? The MonoBehaviour? The caller? The thing it captured three yields ago?

The monobehavior that invoked the routine owns it and is capable of cancelling it at typical lifecycle boundaries.

This is not a hill I would die on. There's a lot of other battles to fight when shipping a game.

DonHopkins 7 hours ago||
And then you're bending over backwards and have made so much more busy work for yourself than you would have if you'd just done it the normal way, in which all your state would be explicitly visible and auditable in the editor.

The biggest reason for using Unity is its editor. Don't do things that make the editor useless, and are invisible to it.

The problem with coroutines is that they generate invisible errors you end up shipping and fighting long after you shipped your game, because they're so hard to track down and reproduce and diagnose.

Sure you can push out fixes and updates on Steam, but how about shipping games that don't crash mysteriously and unpredictably in the first place?

kdheiwns 8 hours ago|||
In all of my years of professional game dev, I can verify that this is not even remotely true. They're used basically everywhere. They're very common when you need something to update for a set period of time but managing the state outside a very local context would just make the code a mess.

Unity's own documentation for changing scenes uses coroutines

voidUpdate 8 hours ago||
Just out of interest, how many serious unity devs have you talked to?
DonHopkins 7 hours ago||
I've talked to some non-serious unity devs, like Peter Molyneux...

https://news.ycombinator.com/item?id=47110605

>1h 48m 06s, with arms spread out like Jesus H Christ on a crucifix: "Because we can dynamically put on ANY surface of the cube ANY image we like. So THAT's how we're going to surprise the world, is by giving clues about what's in the middle later on."

https://youtu.be/24AY4fJ66xA?t=6486

Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Click. Moo!

https://www.gamedeveloper.com/design/the-i-curiosity-i-exper...

>"I'm jealous that [Molyneux] made a more boring clicking game than I did." -Ian Bogost

>"I also think Curiosity was brilliant and inspired. But that doesn't make it any less selfish or brazen. Curiosity was not an experiment. 'Experiment' is a rhetorical ruse meant to distract you from the fact that it's promotional." -Ian Bogost

mjr00 4 hours ago||
Molyneux is obviously a well-known gamedev figure, but he's always been much more on the design side than programming side, as opposed to someone like Carmack or even J Blow. I wouldn't take his opinions on minutiae like coroutines as authoritative.