Code abstraction: Events and delegates

As a one-man team, indie developer, or hobbyist game developer, your time is more limited than that of a big company or a big team. As such, you need to optimize your development process as much as possible.

Often, your scripts need to contact each other for several reasons: a city finishes up producing a unit and needs to tell the unit manager script that its done and it should actually Instantiate the GameObject and set it up; or a ship arrived at its destination and needs to tell the planet it has arrived and needs to be stored in a hangar.

Whatever your case is, you need to contact other scripts. And sometimes, you need to contact more than one script.

The usual way is to have properties (variables) pointing at the other scripts and running methods. Here’s an example of a production gauge with a timer that notifies the city the production is done.

ProductionGauge.cs
——-
UnitManager unitManager;
CityManager cityManager;

void Update () {
[…] when production of a unit finishes

// Tell the unit manager to actually create the unit
unitManager.Create(unitType);

// Tell the city the unit has finished production
cityManager.FindByName(“Rome”).ProductionDone(unitType);

[…]
}

Now this is fine, but as I started, you need to optimize your speed as much as possible. In order to do that, you need to create your own set of scripts that you can re-use in future projects.

If we keep the code like this, if you want to use the ProductionGauge.cs in another project and you drag just that file, then you’ll end up with errors because the UnitManager and the CityManager are not there, so you need to remove all the code related to those scripts, and of course, you need to modify this new ProductionGauge.cs to fit the needs of your new project (call the PlanetManager instead if its a space game, for instance).

This is a maintenance nightmare, because if you happen to find a bug on ProductionGauge.cs, suddenly you realize you have that bug in both your games, the city game and the space game, so you should go back and fix the city game as well. But you can’t just copy back the ProductionGauge.cs into your city game, because it already contains all the logic for that particular game. Well, you get the idea.

Here’s where Events and Delegates come handy. They allow a layer of abstraction between scripts.

Basically, what you can achieve is for the ProductionGauge.cs to shout “hey! I’m finished producing!”, and any script can listen and act accordingly. Therefore, you don’t need any specific references inside ProductionGauge.cs to any other script. It just shouts to mid air.

Here’s the same example of ProductionGauge.cs with events and delegates:

ProductionGauge.cs
——————–

// Declare the delegate and the event
public delegate void ProductionGaugeFinishedEventHandler (ProductionGauge pg);
public static event ProductionGaugeFinishedEventHandler OnFinishedEvent;

void Update () {
[…] when production is done

// Always check if event is not null before raising it because if
// it is null, then no-one is watching
if (OnFinishedEvent != null) {

// Raise the event on all registered listeners
OnFinishedEvent(this);
}

[…]
}

And on the City.cs side, this would be like so:

City.cs
————–

void Start () {
ProductionGauge.OnFinishedEvent += MyOwnFinishedMethod;
}

void OnDisable () {
ProductionGauge.OnFinishedEvent -= MyOwnFinishedMethod;
}

void MyOwnFinishedMethod (ProductionGauge pg) {
// This method will be executed whenever the ProductionGauge raises its event
}

As you can see, the ProductionGauge.cs does not refer to any other script now, so you can easily use it between projects.

Also, even if you don’t share the code between projects, if with the example above we need the HUD to also listed for that event, the HUD script can simply add itself as listener and it will also get notified when production finished.

So you should use Events on all the scripts you want to re-use in another project or when you need to notify several scripts about something.

Don’t forget to follow us on twitter for news regarding articles and game development.

 

 

@IndelveStudios
@NickVarcha

Demystifying Unity for Large Projects – 6 rules

Hi, I’m Nick Varchavsky, lead developer at Indelve Studios.

I’ve been using Unity since it’s version 2.x (around 2008 or so), and I’ve seen it grow year after year. Along with the engine, the projects done with it grew as well.

One thing I’ve noticed is the general mis-understanding (from my point of view) on how capable Unity is handling large projects, and how to do so. I see a huge misconception on what Unity is, and how one should use it.

If I can explain these tips, you’ll never fall back on using Unity like before.

Throughout years of experience, research, and forehead slaps, I’ve come up with a set of rules I implement here at Indelve. I’m sure this is not the only way to handle large projects on Unity, but it has helped us greatly and worked wonderfully in small teams like in our mobile division, and in large teams like in our current large game Initiative: Red Daw.

You’ll notice some of them are not exclusive to Unity and more general to programming, but since they are part of my mantra, I’ll share them as well.


1- Keep it sharp
Use C#. Plain and simple. There’s no reason to use UnityScript (or what many confuse with “Javascript”). As I’ve explained on another article, there are a series of reasons why I use C# for everything, and completely ban UnityScript from any project I work on.

First, most libraries you’ll find are written in C# (such as Facebook’s or other major SDKs).

Second, UnityScript and C# in Unity have different compiling time. This means they are not compiled together. Hence, if you want a UnityScript to access a C# script, you have to follow specific folder guidelines to achieve that. I’ve found myself in a hybrid nightmare of C# and UnityScript scripts that didn’t see each other, so I had to arrange some on the Assets folder, some on Standard Assets, some on Plugins, etc. to be able to achieve what I wanted. Since then, I chosen to use C# for everything.

Also, it’s not Javascript. Unity’s Javascript is not really Javascript. In fact, it’s actually UnityScript and it lacks a few of the most powerful things Javascript has (for my taste), which is JSON. You can see a more detailed list of the differences here as well, but I’ve found several that make UnityScript a turndown for me. I develop a lot in JS (NodeJS and AngularJS for example), and I absolutely love JS. But when it comes to Unity, I go with C#.


2- The point of no return
When working on large projects, there’s a point of no return (usually pretty early) where you must commit and stick to an engine version (strictly speaking, to a specific version of every library you use). This is true not only to Unity. Although Unity still lacks a good version management like Unreal Engine has.

Also, under no circumstance you should depend on a future feature Unity says they will provide (i.e.: Nested Prefabs have been in the roadmap as the next feature since 2013 and still at the end of 2016, no nested prefabs). If you need a feature, either code it yourself or get a plugin from the Asset store. If you plan the latter, check below on #5.


3- Make your own DLLs
When working with multiple programmers and designers it becomes imperative to protect the code from accidental edits. And if you are working with freelancers, you’re also protecting your source code.

You can create one or multiple DLLs if you want. Here are a couple of uses we have for DLLs:

– Prevents accidental edits
– Protects source code
– Easier version tracking (easier to know all developers are working on the same library version)
– Easier update: you simply send the new DLL instead of the source code script or worse, the full Unity project. This is specially useful if you work with programmers off site
– Easier propagation: you can setup your environment to automatically copy linked DLLs to a master server from which others will update automatically

You can make .NET DLLs in Windows and in Mac as well using Mono. Unity uses Mono so you’re not loosing any special features. Send me a buzz if you need some guidelines as to how to create such DLLs.


4- Unity for Unity
One of the biggest mistakes I find online is wanting to have Unity solve every single need we may have.

As a general rule, I put no game logic on Unity. I use Unity simply as a visual front-end of the game. For example, on Initiative: Red Dawn can be played fully from a linux console. Unity is just a visual representation of that.

Initiative: Red Dawn console view (early version)

Remember,  just because Unity has certain functionality does not mean you need to adapt your code to use it.

Use Unity stuff (i.e.: MonoBehaviours) only for Unity-specific visual stuff. If a class has no visual representation on the game world, then it makes no sense to make it a Monobehaviour or even have it inside Unity.

Don’t use Monobehaviours just for the Start/Update/etc. Use Dirty updates instead.

We have a single MonoBehaviour performing the update to the DLL, and everything else is handled through a dirty update from there, even Unity stuff.

TL;DR
If it has a visual representation, use Unity. If not, goes into the DLL.


5- Asset Store plugins
If you want/need to use asset store plugins, there are a few caveats we always check:

– Make sure the plugin is actively maintained by the developer: you can check the forums, their webpage and comments on the Asset Store itself.

– Always have an empty project to import the plugin, run the demo scenes, and make sure it works. Then, delete all unwanted content (demo content mostly), and create your own UnityPackage to use. Never have developers download the asset from the store, always share your version of it (also check the licensing to see how many seats you need when sharing)

– Just like Unity, you need to stick to a version of the plugin and be very cautious when upgrading

– If the plugin comes with source code and the license allows it, embed such code in your DLL and use it from there. If the plugin does not come with source code, I simply don’t use it. We already have to live with Unity’s lack of source code to add yet another black box middleware.


6- Scene usage

Don’t. Just don’t use or relay on scenes for your end-game. Use prefabs for everything (I mean, everything). If its a GameObject, then it is a prefab, no matter how simple it is.

You can use scenes during development to test specific elements of the game if you must. If you do, plan ahead and make sure each scene is fully playable without the need to go through several other scenes to test a single feature.

In our case, we use different Unity projects for each section of the game: the base on Earth is one project (not a scene, a separate project), the technology tree is another project, etc.

All projects have a shared library containing the DLLs and all shared assets (icons, logos, images, sounds).

Also, since we are not using scenes, we can have multiple programmers working on the same part of the game and it’s just like a script file edit.

If they are changing visual elements (models, animations, etc.), it’s just updating a prefab.

 


Well! I hope I did a fair job explaining our method. Remember, I’m not stating this is by far the best method there is, but it sure worked for me in the past and is working wonderfully now.

Game developing consumes an immense amount of time, which unless you’re doing it fully as a hobby, translates into money which, for most of us, it’s very limited and heavily guarded by our CFOs and alike. So, ensuring you use a cleaner and smoother workflow saves plenty of time in the end.

As always, let me know if you find any issues, typos, or if you want me to go deeper into any topic explained here.

Thanks for reading!

You can follow me on Twitter at

 

Our Inspiration

We grew as computer games did. We’ve returned home with excitement with our box full of floppy disks with that brand new game that came out.

We knew Scorched Earth before Worms, and played forsaken games such as Sokoban, Supaplex, and all-time favorites such as Master of Orion, Space Federation and Transport Tycoon.

We’ve watched with awe the birth of Internet on games, and that first time we played Doom multiplayer cooperative and felt like touching the sky. Not to mention our first Counter-Strike match with unknown people on the Internet…

When you grow along with a generation that watches the inception of the most modern and comprehensive form of art, you simply can’t ignore that calling, that need.

We’ve read Isaac Asimov’s Foundation and Robot series only to dream about space travel and the possibility to step on soil of another planet. Do you imagine that? Setting your foot in another planet? It’s mesmerizing. And for a big part of our lives, we accepted the fact it was just science fiction, and we were just born too early in mankind’s history to be able to travel on space.

We are heavily and deeply inspired by NASA’s unending research and the current private sector pertnership (such as Elon Musk’s SpaceX). We’ve been to the Kennedy Space Center every single chance we had, and beheld with admiration the amazing Saturn V rocket and the new Falcon rockets Elon’s SpaceX is testing and the Curiosity with the answers it may bring. 

We’ve been inspired so much, this game is an homage on all these heroes’ lives by using the art we master: Video Games. That’s why in the game you start off with $100 million, just what he had, and push to become a space magnate from there. 

It’s all up to you: the Talents you hire, the technology you choose to research, the relations you cultivate, the contracts you get, the rockets you make, the missions you launch, and above all, the absurdly ambitious ultimate goal you need to achieve: a sustainable colony on Mars.

This is a game we want to make because this is a game we want to play as it converges on so many angles. And at the same time, bring the space race back to the dinner table conversation, since mankind’s next step is enabling life on other planets.

We sincerely hope you enjoy this game as much as we are enjoying making it.

And realize, despite some overlapping between young and old, we all live our life at the same time window, and though we missed the Teslas, Edisons and Bells, we do got to live with the Carmacks, the Jobs and all the people that reshape our lives and the world.