Unity3D General Tricks and Gotchas

Category : Coding, Games ยท by Jun 13th, 2015

This is a continuation of Unity 2D Tips and Tricks, some of which are adaptable to 3D as well.


1. Translate or Rotate relative to world space
Unity3D’s API doesn’t advertise the optional parameters Translate and Rotate functions as much as their importance merits. By default, translations and rotations are conducted in the local transform space. This is usually convenient, but can be annoying when parent/children relationships are used for their convenience in referencing each other. The optional RelativeTo parameter in Translate and Rotate takes either Space.World or Space.Self, saving us from nasty workarounds.

2. Choosing random enums
Stolen from the Unity Answers thread, a shortcut function to pick a random enum is not provided by Unity3D, but is immensely helpful for fighting technical debt while rapid prototyping.

3. Use a Tweening Engine
Tweening refers to the action of exercising fine-tuned control over the transition of variables, often done through existing mathematical functions. See an example here (automatic-audio warning).

In the context of a game, it is a invaluable time-saving tool for two reasons. Firstly, tweening adds a great amount of polish to a game in very little time; Secondly, tweening engines usually comes with timeline functionalities that dramatically simplify potentially annoying tasks.

For example, consider simulating a ball that bounces once, then stops, fades, and gets destroyed one second after fading. Using Update, we must hand-write the sine function to approximate the trajectory each frame, keeping track of the amplitude and the phase of the function. We must keep variables that track time since bouncing started, whether the ball has finished bouncing, the alpha value of the ball, and amount of time elapsed since the fading has finished. The result is ~20 lines of ugly code that is inflexible to change.

Using something like DOTWeen, we can simply do:

Sequence mySequence = DOTween.Sequence();
mySequence.Append(transform.DOMoveY(100, 0), timeToMove / 2f).SetEase(Ease.InSine);
mySequence.Append(transform.DOMoveY(0, 100), timeToMove / 2f).SetEase(Ease.OutSine);
mySequence.Append(DOTween.ToAlpha(()=> renderer.color, x=> renderer.color = x, 0, 1);


Note that the alpha-tweaking line has some fancy syntax for referring to getters and setters, it will be well worth your time to learn this notation, if only for giving you more power in using the tweening engine.
Note that using a tweening engine, the code is much shorter and more readable, and it’s easier to tweak for different types of effects.

1. Rounding
Unity’s Math.Round function has an odd behavior, from the API:

If the number ends in .5 so it is halfway between two integers, one of which is even and the other odd, the even number is returned.

Here is a more minimalistic round function that behaves according to expectation.

public static int Round(float value){
	return Mathf.FloorToInt(value + .5f);


2. Photoshop Color Management
Unity’s texture import feature does not account for color profile settings in photoshop, as seen here.

The difference looks something like this:
Screen Shot 2015-06-13 at 1.13.29 PM

This is a small detail that could cause massive headaches in reworking textures if not properly dealt with.
To prevent it, select “Don’t color manage this file” on all graphic assets intended for import through Unity.

3. Corrupt Prefabs via Git
As late as Unity 4.6, saving a prefab without saving the scene the prefab is in transmits a corrupt version of the prefab to the remote git server. This is one more reason to attend to the good practice of always saving the scene before a git push.

4. Viewport Space, Screen Space, and World Space
Unity’s Camera class provides a wide variety of useful functions to convert between dimension measurements on the screen, in the view port, and in the game’s world. Distinguish between these carefully:

      The Screen space provides the dimension of the game in pixels. The bottom left of the camera is (0, 0), the top right is (Camera.pixelWidth, Camera.pixelHeight), respectively the width and the height of the camera in pixels. The Z value is the distance of a particular point in the world from camera.

The Viewport space is normalized. The bottom-left of the camera is (0, 0), and the top right is (1, 1). The Z value is the distance of a particular point in the world from camera. This is useful for positioning GUI elements.

The World space is the global positioning space that Transform components inhabit.

Note that when converting between any two spaces, we are not confined within the screen or the port. It’s perfectly valid to ask the Camera to convert from (2, 2, 0) in Viewport space to world space, in this case, we will obtain a point in the world that is about one camera outside of the current camera.

When working within 2D, it’s tempting to use the dimensions of the camera to determine the positioning of GUI elements. I find viewport space to be more reliable, since it’s immutable to both camera size changes and game screen resize.

5. OnDestroy in Child Transform
OnDestroy is a convenient callback, but beware that when a child is destroyed due to it’s parent being destroyed, the OnDestroy function on the child is not called.

6. Proper way of checking whether an object has been destroyed
Due to Unity’s gameObject implementation, checking whether an object has been destroyed in not very obvious. The correct way to do so is:

if(target == null || target.Equals(null)){
	//Assume that target has been destroyed.

This is a handful of code to type for each destruction check, so consider writing a static function under some utility class to handle the check instead.

7. Unity Canvas Crossfade
The new canvas GUI system in Unity seems very powerful, but UI.Graphic.CrossFade and UI.Graphic.CrossFadeAlpha are broken in the sense that both will not work if the color of the Graphic element was change right before them.
The solution turned out to again be Tweens. Example code that I used:

menu.color = new Color(1f, 1f, 1f, 0f);
Color c = new Color(1f, 1f, 1f, 0.7f);
menu.DOColor(c, 3f);

This code shifts the menu’s color from completely transparent to a transparent white in 3 seconds.


Leave a Reply

Your email address will not be published. Required fields are marked *