⬜️ Unity

Updated at 2016-10-04 02:44

Unity is a multi-platform game engine and development toolkit.

Organize your assets. There are multiple ways to do this, find what works for your project. Personally I like to keep related files as close together as possible. Organizing files even by level they are used in might be good idea, keeping all related files close together.

For example:
    _Game - just to namespace your assets from any imported stuff
        Code - scripts and non-scripts, kept close to related files
        Prefabs - usually model + scripts
        Resources - files loaded runtime

Import assets store packages to their default directory. Non-standard directory structure will make updating the installed addon more troublesome. And some of them still expect to run in hard-coded paths.

# bad
# good

Don't include managed color profile when importing image assets. It will distort colors in Unity.

Preferences -> File Handling -> Maximize PSD and PSB File Compatibility.
Color Mode: RGB Color 8 bit

Avoid using too much Instantiate and use object pooling. Reuse game objects by enabling and disabling them. Improves performance.

Keep all your code under a namespace. Protects from conflicts with 3rd party code.

using UnityEngine;

namespace Company.MyGame
    public class Entity : MonoBehaviour
        // !

Use prefabs. If you don't, you can't change all instances of object from one central point.

Use depth (the z axis) to provide layering in 2D games. Remember to set camera to orthographic.

Try to get by with only one scene when doing mobile. Multiple scenes will slow down mobile games a lot. Use a master script that enables root objects that are your different scenes.

Use default mobile shaders for mobile games. They are well optimized but make sure you use the mobile variants.

Understand the flow of the Unity game loop. Each script have these following functions defined that are called in different parts of the game loop and lifetime of the script. If the object containing the script is disabled, the script will also be disabled.

Awake    - Called when the script is being loaded, but once in its lifetime.
           Script can be enabled or disabled.
           Usually used for assigning references to other scripts and objects.
OnEnable - Called when the script is enabled.
Start    - Called when the script is enabled, once in its lifetime.
        FixedUpdate - Called every physics update, multiple times per frame.
    Update     - Called every frame.
    LateUpdate - Called every frame after Update.
OnDisable - Called when the script is disabled.
OnDestroy - Called when the script will be destroyed soon.

MonoBehavior has a lot of predefined callback functions. Here are the most important ones.

Reset - Called when adding the script in editor, use to set defaults.

OnTransformChildrenChanged - Called when child game object list is changed.
OnTransformParentChanged - Called when the parent game object is changed.

OnBecameVisible - Called once when object becomes visible to any camera.
OnBecameInvisible - Called once when object becomes invisible to any camera.

OnWillRenderObject - Called once for each camera where object is visible.
OnRenderObject - Called after all regular scene rendering is done.
OnPostRender - Called once for each camera that finishes rendering the scene.
OnRenderImage - Called after scene rendering is done, for post effects.

OnLevelWasLoaded - Called after a scene is loaded.
OnApplicationPause - Called when app pause changes, true if pause, false if not.
OnApplicationFocus - Called when app focus changes, true if focus, false if not.
OnApplicationQuit - Called when app is quit.

OnCollisionStay - Called once per frame for every collision, has other collider.

OnTriggerStay - Called once per frame for every trigger, has other collider.

OnGUI - Used to draw old UI system stuff.
OnDrawGizmos - Used to draw debugging gizmos.

Learn to use coroutines. They are the number one thing that helps to keep performance bearable.

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    private void Example() {
        var coroutine = CoroutineExample();
    private IEnumerator CoroutineExample() {
        yield return null // Continue as fast as possible.
        //yield return new *YieldInstruction* - Where YieldInstruction is...
        //WaitForSeconds(1.0f) - Continue after given time.
        //WaitForFixedUpdate() - Continue after physic calculations.
        //WaitForEndOfFrame()  - Continue just before rendered screen is shown.

Don't unreference->create C# objects every frame. This will trigger extra garbage collections, reducing the performance a lot. The most common is problem is concatenating strings frequently.

using UnityEngine;

public class ExampleScript : MonoBehaviour {
    public GUIText scoreBoard;
    public int score;
    private void Update() {
        // bad, will create new string, losing the reference to the old one
        string scoreText = "Score: " + score.ToString();
        scoreBoard.text = scoreText;

Make your game frame rate independent. Time.deltaTime is the time in seconds it took to complete the last frame. You usually multiply your changed value with this.

  • FixedUpdate frame time is constant, you get it from Time.fixedDeltaTime.
  • Both reported fixedDeltaTime and deltaTime are multiplied by global Time.timeScale variable, allowing to stop, slow down or speed up time.
using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour
    private void Update()
        transform.Translate(0, 0, 1.0f * Time.deltaTime);

Avoid using Resources API. Assets in Resources folders are harder to memory optimize and bigger folders cause slower builds and startup. For example; initializing Resources folder with 10,000 assets adds multiple seconds to mobile game boot time, and this happens even if the assets are not needed.

Create a template project for yourself / your organization.

  • Force Text enabled
  • visible meta-files
  • your / your company's name,
  • default sound settings
  • common Tags and Layers
  • common cameras
  • 3rd party tools that you use across projects
  • it should be maintained
  • it should be stored in a version control system

Consider using ready-made backend-as-a-service. They provide SDK with authentication, multi-device sync, virtual currencies, items, in-app purchases etc.

GameSparks - Older, more mature service.
PlayFab    - Newer, adding features fast, simpler.
Amazon     - Cognito, DynamoDB, etc. Good but low-level, requires a lot of code.

Learn from the best by decompiling an Unity game and read the source:

  1. Install the game.
  2. Search *_Data/Managed directory for the following files:
    • Assembly-CSharp.dll (C# stuff)
    • Assembly-UnityScript (UnityScript stuff)
  3. Install dotPeek.
  4. Start dotPeek.
  5. Drag the dll files to the Assembly Explorer tab.
  6. Now you can read all the source code under Assembly-CSharp.

Notable Unity Plugins and Tools:

  • JsonFX: JSON encoding and decoding. Nowadays Unity has JSON encoding too though, but it's very limited.
  • sqlite3: small local database, good if you have a lot of local data.
  • Twine: interactive non-linear story definition tool
  • RagePixel: pixel art tool for Unity
  • VHS Pro: retro post processing filters
  • Shroud Cloth Simulation Engine: cloth simulation
  • RAIN: free AI library
  • LeanTween: tweening library, free
  • MoonSharp: LUA interpreter for C#
  • DotNetZip: zip and unzip files.
  • Rewired: input system extension
  • LINQ to GameObject: allows using LINQ to query game object hierarchies.