Sign in to follow this  
Dinosaursssssss

The Unity Thread

Recommended Posts

Threading in Unity is weird; if you use built in C# threading methods, you won't have access to the unity API, so if you want to do vector or quaternion math you need to basically rewrite those classes. It's a hassle, but definitely possible. If I remember right there is some rendering and other stuff in the background that is threaded too. There was a talk I linked on the first page called 'A Little Math for your Big Ideas' that touches on how to handle threading in Unity; I believe in his buoyancy system, all the vector positions of the water surface mesh are calculated in a separate thread.

 

Also it's true that foreach/linq performance isn't the best, and people will rightly tell you not to use them for performance reasons, but as long as you aren't on using them in Update() or running them against enormous data sets it's really not noticeable. If you're doing hobbyist development for PC or another platform with a decent amount of ram, it's not something I would worry about at all.

Share this post


Link to post
Share on other sites

I can only speak to the for each issue, as I went through and started optimizing things in my code one day and that was on the list of things to address. After removing about 70% of my for each loops, I saw no change in performance. If you don't overuse them, I think it can be OK. If you're designing for the PC, you could probably blow off that concern completely for something like a tower defense game.

Share this post


Link to post
Share on other sites

OK, so.  Where to begin.

 

I've been programming for 25 years, 10+ professionally, but I've never tried my hand at games.  For reasons unclear even to myself, I've recently taken an interest in games programming, to the point of actually downloading Unity and working through a few tutorials.

 

The framework is always harder to learn than the language.

 

I picked Unity only because it seems to be snowballing.  The best framework, for me, is the one I can get the most help with.

 

I've worked on large projects in C, perl, common lisp, scheme, java, scala, ruby, bourne shell scripting (god help me), javascript, and several DSLs that escaped containment and grew into shambling half-designed full-blown languages.

 

My problem is not learning C#.

 

My problem is that it seems like programming games in any modern framework means I have to give up even the puniest, least powerful conveniences borrowed from functional programming that I've grown accustomed to in non-games languages and frameworks.

 

Things like map(), fold(), and filter().

 

Apparently you can't use LINQ in Unity without utterly ruining performance.  You can't even use foreach in lieu of a for loop?

 

Mind you, I really don't have anything fancy in mind for a first outing; I've been inspired mostly by the Tower Defense episode of Three Moves Ahead.  But though it's mechanically simple, that's a type of game where you're going to be manipulating a lot of collections of objects, you know?

 

So... do I really have to give up ten years of progress and go back to lots (and lots and lots and lots) of nested for loops?

YUP!  Welcome to the wonderful world of games programming, where nothing works the way you'd expect!  So a few things about Unity I learned after working with it for a few years.

 

- You can use advanced C# functions, like LINQ functions, Tuples and the like, but you'll have to change the .Net compatibilty in the editor which is not guaranteed to work, so do so at your own risk.

 

- Unity doesn't use threads, it uses "Threads".  In fact, everything in Unity (or at least all the scripts you are going to run) will happen on a single thread, and even trying to manually create a thread and run that yourself will cause Unity to just do whatever you are doing in it's original thread.  There is some similar functionality in Unity, but to be honest it's not going to get you anything in terms of performance or capability so I wouldn't bother.

 

- Unity isn't great about letting you know this, but it's almost always a better idea to create very specific components than complex machines in a single script.  It is fundamentally an engine created for designers and non technical people, so a bunch of it is going to drive you crazy.  For example, if you wanted an AI Brain you'd probably want a script for the brain controller, another for the Brain Data, another for the motor, each of the sensors, the animator, the weapon, the health system, and so on and so forth.  Unity really wants each of your scripts to basically be independent, with as few dependencies as possible.  Essentially if you want to use Unity, accept the fact that when it comes to one or the other, convenience will always win out over performance.

 

- Ahh the good old foreach loop.  You aren't allowed to use that anymore, it is god damn terrible.  Anything that allocates memory is something you'll want to use sparingly if at all, which basically means you need to go back to Arrays as often as possble or Lists when it is more convenient.  This goes for objects and prefabs as well, but for the moment you probably won't run into anything too crazy unless you're trying to make some kind of RTS.

 

- A good trick, and I'm not sure if this is different in other applications, is to not necessarily nest for loops but have everything either toggle flags or raise events about what it is doing or has done.  This should help to keep your logic relatively flat, but it will result in a situation where you find yourself working with a preponderance of objects and interconnected systems.  Whatever organization system works best for you, go with that.

 

- Games, particularly modern games, are more difficult to script than older ones because they have so much fluff in them.  You can't just just delete an object that is hidden by an explosion or push a thing offscreen, it needs sounds, animations, particles, UI, all kinds of shit.  It'll frustrate you at first, but try to get used to the idea that scripts and systems don't talk directly to each other but simply make their states available to be worked on

 

- Finally, and this is most important, you aren't programming anymore, you are scripting.  It seems like a weird distinction to make, but the differences will become clear the further in you go.  As your games get more complex you'll start having systems on top of systems on top of systems, and there really isn't any kind of explicit control between them unless you write them that way (which will make your scripts a pain to debug).  You should write your systems such that they operate on their own and respond to things happening, but can't necessarily be controlled or dictated by other systems outside of a very specific context.  The things that operate on systems aren't managers, they are handlers (if that makes sense)  As an example, I wrote a targeting system for my last game that comprised of a targeting fuction in the player's control script, a targetable object, a weapon that dictated the aiming behavior depending on the state it was in, a handler for the targetable objects.  So in that system here is basically how it worked

 

- Controls of the player determine if the system is ON or OFF

--- If the system is ON, the target handler continually updates a list of targetable objects, and picks the best one each frame.  Whenever it selected a new target, I raised an event (C# event, those work fine) that altered the player's reticle, and a bunch of other minor stuff like moving and ability use (that often created conflicts)

--- If the player hits the targeting button, the system is Turned On, and the Target Handler informs the player's control script which object is targeted.  From here the player's control script would manage the player's look direction, and the camera control script would attempt to place the camera somewhere between the player and the object they are targeting within a tolerance.  This would also pop some UI stuff, and the Thing that was targeted would receive a notification that it was just targeted (so the AI can begin attacking the player for example)

--- If the player released the targeting button, the Player's targeting apparatus would inform the handler that the target had been released, and it would go back to cycling targets, and update a list of the recent targets so the player could quickly snap between targets like in Call of Duty

--- Player facing control would revert to the player's currently held weapon, the best example being a sword weapon which maintained the player's facing direction throughout the duration of it's swing.  Also, the motor would be informed of the change and control the player's facing direction when a weapon wasn't being used, and the camera control script was told to simply follow the player again

 

Now here is where it gets weird

--- This same targeting system also needed to be used during our cutscenes for various reasons, so I had to put a number of explicit hooks in the camera control script and targeting system to allow the artist to make it possible for all the stuff the player could do via their control script in a cutscene.

--- Certain enemies (Bosses mostly) could disable the ability to be targeted temporarily, however doing so doesn't break the target lock, it simply started a search for a new target (the same as when the system was OFF)

--- The facing logic was controlled somewhat by all these systems, but needed it's own facing change timer (it is a 2D game) so that we didn't get any sprite flickering, so none of these systems, while they did exert some control over the player's facing direction, were in direct control of it at any time

--- The player can be stunned in the game, which turns off the targeting UI, but doesn't necessarily break targeting, which caused a whole bunch more headaches

--- There are a number of other conflicts that arose, each of which were due to edge cases and needed to inform all the other systems involved in this step of their changes each frame

 

Now the good news is that once this was all together it was rock solid, and we were able to use the targeting system for all kinds of stuff, from turning the player in a cutscene to changing the state of an object when it was the "best" targeting option, and so forth.

Share this post


Link to post
Share on other sites

Thank you, itsamoose, that's helpful.

 

And yes, I've worked with heavyweight frameworks before-- which is why I say learning the framework is harder than learning the language.  I was expecting from the get-go that I'd be trying to figure out how Unity wants me to organize and design things, rather than dreaming up an architecture and then trying to figure out how to impose it on the framework.

 

But it's definitely a bit of a shock to see such big and helpful chunks of a language (or standard library, if we're picking nits) walled off by a framework.

Share this post


Link to post
Share on other sites

That is kind of the most frustrating part of Unity--it doesn't really care how you organize things.  I suppose that is fine for smaller projects or if you like the freedom, but really the onus is on you to be very strict about your organization.  From my experience this basically means a few top level folders, and a pretty aggressive use of the search function, because given enough time you just lose track of where stuff is.  The part about the language features not being present is a bit of a pain as well, I think even namespaces were only recently supported.  I think if you check out the Unify Community wiki there are a few helper libraries, and you'll definitely find yourself writing all those things as you go.  One word of Advice I would have is to take some time to look into the Editor features. There is a ton of stuff in there that makes the day to day work so much easier, and the documentation has gotten much better in recent years.  Oh and attributes are a life saver and from what I've seen pretty well supported.  Even as far as game engines go Unity is a pretty weird one.  It's incredibly feature rich, but almost to the point of being useless.  I mean I don't see a situation where a team would be cool with 3 scripters all writing game code that needs to talk to each other, but doing so in 3 different languages (Boo, Javascript, C#), but you can do it!  So if you really want to get right down to it, the reason why the cooler C# features aren't supported is because there isn't a similar feature in Javascript or Boo.

Share this post


Link to post
Share on other sites

The framework might not have an opinions about where you should put your files, but the how-to videos I've watched so far sure do seem consistent about telling you which folders to make and what to put in them.  That's not quite the same as a framework that enforces that kind of convention, but it's pretty clear there's something of a "normal place to put things" in the community.  Of course, for all I know, that's a relatively recent development...

Share this post


Link to post
Share on other sites

Has anyone used Strange IOC before? It's an inversion of control/dependency injection framework that sounds really neat. I've been considering swapping out my crummy event system to use theirs but I wanted to wait to hear from someone who's actually implemented the framework before spending the time since I'm on a bit of a schedule. http://strangeioc.github.io/strangeioc

Share this post


Link to post
Share on other sites

Alright, reporting back from messing with StrangeIoC a bit...seems really solid, potentially a really great way to decouple your project and keep things clean. I dug the Unity (different Unity) DI stuff in .NET so I was hoping this'd be a good replacement, but in my reading I discovered that Strange doesn't run on any modern consoles. So I'd super highly recommend checking it out if you're working on a specifically PC/Web/Mobile project, but for me, I don't feel comfortable limiting my current project. This tutorial was helpful for filling in the lack of a comprehensive tutorial in the docs. 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this