ORGANIZING PROJECTS IS IMPORTANT: 7 COOL TIPS!
1. ORGANIZING PROJECTS: EMBRACE WHAT YOU CAN’T CHANGE
It’s not uncommon to “import” bad habits when we start working with a new engine. By bad habits I mean the way we were used to work with other engines. That’s a mistake, though – especially when it comes to Unity, as it encompasses a set of qualities that you’ll want to embrace rather than change.
In my previous projects I used to have a folder called “3rd” in which I kept all assets created by third-parties. However, I noticed it caused some issues when I needed to update plug-ins, for example. So now I create a folder called “
_game” (the underscore makes it appear on top) and leave everything in the main directory.
The following folders receive a special treatment within Unity: Standard Assets, Pro Standard Assets, Editor, Plugins, Plugins/x86, Plugins/ x86_64, Plugins/Android, Plugins/iOS, Resources, Editor Default Resources, Gizmos, WebPlayerTemplates and StreamingAssets.
Therefore, if you organize your project in a way that a folder with the names listed above are necessary, you’d better change your folder’s name – and then you are obviously free to use the folders listed above if they are run according to Unity.
Basically, my projects are organized as follows:
assets: rough stuff that came from the art and is yet to be configured within Unity;
resources: objects that need to be loaded on demand;
scenes: the scenes of the game;
scripts: in this file I keep all the “logic” that’s behind the game.
All the other folders – listed below the aforementioned ones – are added to store plug-ins and third-party packages.
I like to keep the names in English because I feel it is important to have a certain “style”. It is also nice in case you need to work with people from abroad.
2. ORGANIZING PROJECTS: BUILDS
Resorting to constant builds throughout the development process is an interesting approach. After all, what you see in your Unity’s editor is not what you get in your smartphone – which is the environment where the game ultimately needs to work.
The “Resources” folder also has its own traits. Everything that’s stored in there will be a part of the build, whether the game uses it or not. The reason for this is Unity’s readiness to load the folder dynamically as soon as the Resources.Load() command is applied.
If there is an asset in any other location of the project then such an asset will be added to the build only if it’s referred to a game object within the scene.
3. ORGANIZING PROJECTS: ABSTRACTIONS
When you develop a game for smartphones you must integrate it with assets from third-parties (ad systems, social medias, online stores and so on). This integration is often made by a so- called “package” (i.e., a .unitypackage file). When you install it, all scripts and other necessary assets are added to your project – normally in the root folder (and that’s the reason I keep my distance from this folder).
Some of these packages are extremely well-done and documented; some are not. Whatever is the case with the package you chose to use, it is important that you don’t try to meddle with it. After all, packages are updated very often, and this is not their developer’s choice, but a result of the constant OS updates and modifications in their rules and regulations. The stores are forced to update the packages accordingly.
Creating a script of your own is a good method to allow updates to run smoothly. I do it in the _game/scripts/connect folder: I write a script that “connects me” to every plug- in installed in the game. Therefore, this script is also responsible for “covering the gap” between my project and the aforementioned plug-ins.
4. ORGANIZING PROJECTS: ASSET STORE
The Asset Store is one of the greatest things about the Unity.
I say so because it really saves a lot of programming time.
Let’s say you want to sell items and money packages for your game. In order to do it manually, you will have to study the application programming interface (API) used by Apple, create a plug-in in objective-c and use it in Unity to make the sell. In case you want to publish it in the Google Play you will have to study its own API and create a Java plug-in using your old plug-in so that both stores can be used.
Let’s also say you’re an awesome programmer with the necessary skills to do all this work in about a week. If your fee is comparable to the ones practiced in China or India – circa US$ 5 per hour – then we would have something like this: 5 days X 8 hours X US$ 5 = US$ 200.
For US$ 175 you can buy a package called Unibill that offers support for seven different stores. Unibill also includes other very convenient tools, such as a currency and inventory manager. Last but not least, you have just won an extra week to work on what’s really important: the game!
As far as originality goes, when it comes to audio and visual assets bear this is mind: the user could not care less. Big companies all over the world buy stuff that is already available in the internet and add it to their games with no second thoughts.
5. ORGANIZING PROJECTS: TYPES OF GAMES
We call “static” those games with preordained environments that the user explores and where he achieves things; “dynamic” games are those where the environment itself is dynamically built in accordance to some kind of logic.
Developing one type or the other makes a huge difference when it comes to Unity. As far as I could observe the engine is meant to work mainly with the first type (i.e., static games). However, I don’t mean to say it is impossible or too complicated to use it with the second type. But you need to take notice of some additional concerns.
My company developed a game called Breakloose. It is an endless runner that takes place in an apocalyptic future when the Earth is infested with zombies. It is a game of the second type – a dynamic game – because the scenery and the obstacles are “reprocessed”.
Because of this I could not mark those “recyclable objects” as static, which is one of Unity’s main advantages:
6. ORGANIZING PROJECTS: OBJECT POOLING
Unity has a wide range of commands that do make our life a lot easier, but sometimes
the use of such commands can cause the game to come to a standstill. It depends on the situation, of course, but it can definitely happen.
For instance, the Instantiate and Destroy commands are responsible for the creation and the elimination of objects, respectively. They both work fine, but demand a lot of processing. Using them during the gameplay in a game like Breakloose would make it virtually impossible to run.
So when the game loads, all the objects that I will need must be created.
When something is marked “static” Unity understands it won’t move, and therefore the engine no longer performs dozens of operations in regards to this object. However if the positioning properties of this very same object are altered in any manner the engine will have to find a way to make it move – and at a high cost: excessive processing rate.
Before the main menu appears. In this sense, whereas the user runs, the necessary objects are captured from the pool and displayed in the scene; when these objects are no longer visible they are put back into the pool.
Thus we can say that the pool is nothing more than a deactivated GameObject that is used to store other GameObjects.
There are several pooling plug-ins available in the Asset Store, but since this is a fairly simple operation we opted to create our own:
public class Pool : MonoBehavior
private GameObject pool;
pool = new GameObject(“_pool”); pool.SetActive (false);
// adds here
Add (Resources.Load(“gui/InGame”), 1);
Add (Resources.Load(“gui/MainMenu”), 1);
Add (Resources.Load(“gui/GameOver”), 1);
private void Add(Object obj, int count)
for (int i=0;i<count;i++)
GameObject tempObject = Instantiate(obj) as GameObject; tempObject.gameObject.name = tempObject.gameObject.name.
tempObject.transform.parent = pool.transform;
public GameObject Pic(string name, GameObject newOwner, Vector3 position)
for (int i=0; i<pool.transform.childCount; i++)
GameObject current = pool.transform.GetChild(i).gameObject;
if (current.name == name)
if (newOwner==null) current.transform.parent = null;
current.transform.parent = newOwner.transform;
current.transform.position = position; current.transform.localScale =Vector3.one;
public void Drop(GameObject obj)
obj.transform.parent = pool.transform;
Our pooling system consists of three commands:
Add: it adds items to the pool;
Pic: it picks an object from the pool so that it can be employed in the game;
Drop: it returns the object to the pool.
As you can see this system moves the object when its parent is switched. If the object is marked as “static” be prepared to hear Unity complaining a lot…
“player”, collides with it. When this happens a trigger is activated inside the trap, which in turn activates the verification of what’s the tag applied to the GameObject that is involved in the
incident. From there a decision on what’s supposed to happen next comes about:
public class Trap : MonoBehaviour
void OnCollisionEnter (Collision
7. ORGANIZING PROJECTS: LAYER COLLISION MATRIX
Unity offers several ways to make it known that an object collided with another. The most
widely applied is the “tag”.
Let’s imagine there’s a trap in the ground and the player, which is a GameObject marked with the tag
Debug.Log(“The player fell into the trap!”);
This is a very interesting technique, but if the player is the only one with the attributes to fall for that trap, then the verification is pointless. Besides, all GameObjects with similar physics applied would end up colliding amongst themselves. That’s why Unity offers us an area where we can manage an array of situations under which layers are caused to collide (i.e., a collision matrix).
For this example I came up with three layers:
player: that’s where the player is;
enemy: that’s where the enemies are, including the trap;
bullets: these are the bullets fired by the player.
Initially, when you create a layer using Unit, the collision matrix looks like this:
In the above case, all layers are set to collide, but let’s make the configuration as follows:
You can see that the enemy collides with the player, the bullets and the ground (Default), but the player only collides with the enemy and the ground. This solution takes it easy on the engine physics when it is time to trigger the events and calculations that make everything work properly – thus making the game more manageable in terms of processing.