Go to Top

It's easy to make mistakes when you are new to Unity. Let this guide help you avoid the most common pitfalls.

There are a number of "gotchas" that hit pretty much everyone new to Unity programming.  Sometimes these are due to you being new to programming in general, and sometimes it's due to the fact that Unity uses a slightly unusual method of attaching multiple scripts to a game object.

This overview tries to take you through the ones we see most often on Unity Answers.

The Gotchas


How to access a variable or method on another script or object

How to access a variable or method on another script or object

There is also a really great tutorial and video on GetComponent which you can read and watch in C#  or in UnityScript

So you've written two scripts and you want to access variables or methods on one script from the other one, but you can't quite work out how to get a reference to the script or how to get the variable.  Lets call the script that wants to access the variable the caller and the script that contains the variable or method the target.

You may be tempted to declare variables as static so that you can access them easily without having to actually reference the object on which the script is placed.  This is a very bad idea unless you know what you are doing.  If you are new to programming avoid static until you fully understand it.  Static variables are global variables and should only be used in rare and quite advanced scenarios.  In fact you could happily program a complicated game and never ever define a variable as static.
On Unity Answers we often see questions that say something like - when one of my enemy dies, they all die.  This is normally caused by the developer using static variables because they couldn't figure out how else to access the information that they were looking for.  If this applies to you, read on!

So to get the target script you need to know the object that it is attached to.  There are five ways you can know that:

1. The target script you want is attached to the same game object as the caller script.

In this case you just need to insert a call to GetComponent, which returns the script attached to the game object on which you call it.  If you don't put something infront of GetComponent it will return a script attached to the same game object.

In Javascript you should use GetComponent like this:

GetComponent(TargetScriptName).someVariable = someValue;
GetComponent(TargetScriptName).SomeMethod();

In C#:

GetComponent<TargetScriptName>().someVariable = someValue;
GetComponent<TargetScriptName>().SomeMethod();
Do not use the version of GetComponent that takes a string.  When you call GetComponent without a string the return value is already of the correct type and you can access your custom variables and methods.  If you call GetComponent("TargetScriptName") you will get your script, but the compiler doesn't know what type it is so you cannot access your custom variables and methods.

2. You want to access the target script on another object because you've collided with it, or invoked a trigger in the caller script

In this case your method already has a reference to the other object being passed in, either as a Collider in the case of OnTriggerXXXX functions or as a Collision in the case of OnCollisionXXXX

In this case you just need to use GetComponent on the thing you've collided with.

In Javascript this would like:

function OnTriggerEnter(other : Collider)
{
      other.GetComponent(TargetScriptName).someVariable = someValue;
}

In C#

void OnTriggerEnter(Collider other)
{
      other.GetComponent<TargetScriptName>().someVariable = someValue;
}

A collision event takes a collision, so you just need to get something that represents the other object and call get component on that:

function OnCollisionEnter(collision : Collision)
{
       collision.collider.GetComponent(TargetScriptName).someVariable = someValue;
}

Or in C#

void OnCollisionEnter(Collision collision)
{
      collision.GetComponent<TargetScriptName>().someVariable = someValue;
}

If for some reason you want to set a variable on some child of the object you triggered or collided with then you can use GetComponentInChildren.

You should know that GetComponentInChildren also searches the object you call it on.

3. You have a relationship between two objects that you can establish using the editor or set using script when the relationship is created

So in this case you have a relationship between two objects, not because they are currently interacting, but rather because they have some other long term relationship.  For example an enemy might be chasing the player, a player may have "locked" a weapon onto an enemy, or perhaps the player is currently riding in or on some vehicle.

In this case you want to have a variable in your caller script that references your target script.  The easiest way is to define that variable as being of the type TargetScriptName but it might be that you have some other kind of object referencing variable like GameObject or Transform.

Be aware that calling GetComponent is not "free" from a performance standpoint.  Even if it means having multiple variables that refer to the same GameObject it is worth doing this for performance purposes.  You might cache these references by calling GetComponent in Awake or Start on a public variable that was configured to reference the object.  Just be aware that if you change one variable at runtime, you should make sure that they all change.

You will assign the variable using the inspector if the relationship can be created at editing time - or if you assign it at runtime you will use either method 2 (above) or method 4 (below) to get the component and set up the variable.

Here's an example of creating a long term relationship due to a trigger:

var targetScript : TargetScriptName;

function Update()
{
     //If we have a target, and that target is ready to be targeted
     if(targetScript && targetScript.someVariable > 100) 
     {
         //Do one thing
     }
     else
     {
         //Do something else
     }
}

function OnTriggerEnter(other : Collider)
{
     //Check whether the thing we hit can be a target
     var target = other.GetComponent(TargetScriptName);
     if(target)
     {
           //If it can then target it
           targetScript = target;
     }
}

4. You can find the object that has the target script, by searching by name or tag

This is by far the most costly way to find another object.  You should seriously consider finding things and storing the result once if you possibly can, in Start or Awake would make most sense.

If you can find a game object then you can just call GetComponent on it in the same way as you did using method 2.

There are several ways to find the object - you can use GameObject.FindWithTag or GameObject.Find to search everywhere in the scene.  Or you can use transform.Find to search the children of a game object.  Whatever you use to find it, you will them employ method 2 to access the script you are looking for and potentially cache the result so that in future you have a long term relationship and can use method 3 to work with the object in subsequent functions.

TargetScriptName targetScript;

void Start()
{
       targetScript = GameObject.Find("someObjectName").GetComponent<TargetScriptName>();
}

void Update()
{
      if(Vector3.Distance(targetScript.transform.position, transform.position) < 10)
      {
          targetScript.someVariable -= someValue;
      }
}

5. You have another component on the object, but its not the one with the script you want

This often happens when you are traversing the hierarchy, or you just have another script on the same object.  In essence this is pretty much the same as method 2.

For instance if you wanted to get a script on all of the children of the object your caller script is attached to:

for(var t : Transform in transform)
{
     target = t.GetComponent(TargetScriptName);
     target.DoSomething();
     target.someVariable = someValue;
}


Rigidbody,how does that work?

Rigidbody,how does that work?

So you just spent the last 3 days with no sleep, trying to make your object act realistic. You went over most of the physics website to fully understand the principles of gravity, friction, collision and others. But then you hear about Rigidbody and you feel like a growth of anger inside. And you go "Naaa come ooon"

Rigidbody is a component that allows to apply fundamental realistic physics to an object without doing much (or almost).

Now how to use it? I would recommend to download this projet and see the video below:

I want explosion but nothing happens!!!

From the project above you can try to add this code:

if(Input.GetKeyDown(KeyCode.E)){
	float radius = 10.0F;
   	 float power = 1000.0F;
	Collider[] colliders = Physics.OverlapSphere (_transform.position, radius);
	foreach(Collider col in colliders){
		if(col.rigidbody){
			if(col.rigidbody != gameObject.rigidbody)
				col.rigidbody.AddExplosionForce (power, _transform.position, radius);
		}
	}
}

This code makes sure the actual object is not affected by the explosion. You can now add this to your sphere so that it makes the scaffolding explode.

Simply, you define the radius and the force of the explosion. You collect all colliders around in a certain radius. Then you check which ones have a rigidbody. Finally you check if this rigidbody is not the object.

You just created a bomb.


Colliders: how to make sure you get OnCollisionXXXX and OnTriggerXXXX functions called in your scripts

How to make sure you get OnCollisionXXXX and OnTriggerXXXX functions called in your scripts

In order to collide both objects must have colliders attached.  If you want OnCollisionXXXX then the objects should not have isTrigger set to true, if you want to have OnTriggerXXXX then the objects should have isTrigger set to true.  You must also follow the rules below.

This is one of the most common problems.

There are some two important rules:

You should have a Rigidbody component attached to the game object that has the script containing the OnCollisionXXXX, OnTriggerXXXX methods on it.

This rigidbody can be set to isKinematic = true to ensure that you don't have physics affecting your object if you don't want it.

Collision detection is part of the physics system in Unity.  You may not want to use physics for your game, but if you want to use collision detection then you need to add Rigidbody components.  isKinematic = true Rigidbodies do not apply physics to your objects.

At least one of the parties must have a rigidbody that isn't asleep

To improve performance Unity will put rigidbodies to sleep when they stop moving.  They will be awoken by another rigidbody colliding with them, presuming that body isn't asleep.  However if you just move or make a collider on an object without a rigidbody, or whose rigidbody is not awake then your collisions will be ignored.

Attach a kinematic rigidbody to any colliders you will create or move if they don't have a rigidbody already.

Other important considerations

There are a number of other rules that concern what things will make a collision occur.

Mesh colliders will only collide with other mesh colliders if both are convex.  If you need to collide with concave meshes then the other party should be constructed from primitives. See below.
Mesh colliders are one sided - they only collide on the side where the normal is pointing outwards.
Mesh colliders are subject to back face culling.

You can construct colliders for an object out of multiple primitives - this gives you the ability to simulate quite complex objects.  What you need to do is attach multiple child game objects to the object that you want to collide with.  Give that object a rigidbody.  Attach primitive colliders to the child game objects, size and scale them accordingly - the compound shape of them will comprise your new collider.


Getting your Input to work properly

Getting your Input to work properly

Beginners often end up wondering why their input does not report properly. They set it all up according to the docs (at least they think so) but sometimes they feel nothing is happening. Most of the time, the issue comes up when trying to control some physics via the Input. Since, physics is placed in the FixedUpdate, it would make sense to add the Input there too. Wrong.

Update is machine dependent, that means each computer can  have a different frame rate depending on the processor and the processes actually running on the machine.

FixedUpdate is user-defined. You can modify its value from  the Physics Manager by selecting Edit->Project Settings->Physics from the menu bar. The default value for Fixed Timesteps is 0,02 which represents 50 fps. A smaller value will ask the system to run FixedUpdate faster. Note that the value is a request but the computer on which the game is running might not be able to run at that speed.

Now, Update and FixedUpdate both run independently, it means for one Update, you may have one, many or no FixedUpdate. If your computer runs 100 fps but the FixedUpdate is 50fps that simply means for two Updates we have only one FixedUpdate.

InputFixed

So this is what you should not be doing:

using UnityEngine;

public class Test:MonoBehaviour{
    void FixedUpdate(){
        if(Input.GetKeyDown(KeyCode.Space)){
           //Action
        }
    }
}

This is what you could be doing instead:

using UnityEngine;

public class Test:MonoBehaviour{
    bool action = false;
    void Update(){
         if(Input.GetKeyDown(KeyCode.Space)){
             action = true;
         }
    }
    void FixedUpdate(){
       if(action){
           //Action
           action = false;
        }
    }
}

The Input in the Update is checked every frame guaranteeing no Input gets discarded. A variable is modified in the Update and used in the next call of the FixedUpdate. The boolean is set back to false to ensure that the action does not get repeated endlessly.


Make something happen in the future | Coroutines and Invoke

Make something happen in the future

Coroutines are complicated overkill if you just want something to happen in the future.  You may tie yourself up in knots by forgetting to start them properly in C# or just get confused over what they are for.  If you are starting Unity and you want something to happen in the future forget the coroutines for now and follow this advice.

Just for the sake of it, here is a way to create a timer:

float timer;
int waitingTime;

void Update(){
    timer += Time.deltaTime;
    if(timer > waitingTime){
        //Action
       timer = 0;
    }
}

The variable timer is increased each frame with deltaTime (the time elapsed between this frame and the previous one). The variable is compared each frame with waitingTime which stands for the amount of time we want to wait. When timer becomes greater than waitingTime, the statement is true, the action inside the statement are performed and finally timer is set back to 0 for the process to start again. Wrapping the timer into a boolean will allow triggering the timer for a particular situation:

using UnityEngine;
using System.Collections;
public class Test:MonoBehaviour{
    float timer;        
    int waitingTime;
    bool inside;

    void Start(){
        timer = 0.0;
        waitingTime = 2;
        inside = false;
    }

    void Update(){
        if(inside){
            timer += Time.deltaTime;
            if(timer > waitingTime){
                //Action
               timer = 0;
           }
       }
    }

    void OnTriggerEnter(Collider other){
        if (other.gameObject.tag=="Player")inside = true;
    }
   void OnTriggerExit(Collider other){
        if (other.gameObject.tag =="Player"){
            inside=false;
            timer = 0;
        }
   }
}

The example above shows how to create a timer suitable for triggering an action when the player remains inside a zone. For instance if the player enters a fire zone, simply harming the player in the Update would kill him within a second. With the timer we can harm him every x seconds.

Still, Unity offers better solutions as shown in the next part.

Make an object live for a few seconds

If you want your object to only appear on screen for a few seconds, just destroy it in Start!  Destroy can take a parameter which is the delay before it actually gets killed.

function Start()
{
       //Destroy the game object in 5 seconds
       Destroy(gameObject, 5);
}

Delaying an action

You want something to happen and another action after a defined amount of time. UnityScript and C# use different action for the same result. In those example, the check variable is necessary to enter the statement. When entering it is set to false, after 2 seconds it is set back to true.

UnityScript

#pragma strict
var check :boolean =true;
var i:int =0;

function Update () {
	if(Input.GetKeyDown(KeyCode.A)&&check){
		check = false;
		print("Inside" + i++);
		WaitForIt();
	}
}
function WaitForIt(){
 	yield WaitForSeconds(2.0f);
	check=true;
}

C#:

using UnityEngine;
using System.Collections;

public class Wait : MonoBehaviour {
	public bool check =true;
	int i =0;

	void Update () {
		if(Input.GetKeyDown(KeyCode.A)&&check){
			check = false;
			print("Inside" + i++);
			StartCoroutine(WaitForIt());
		}
	}
	IEnumerator WaitForIt(){
	 	yield return new WaitForSeconds(2.0f);
		check=true;
	}
}

Running those scripts, you see that you can press A and it prints out"Inside" and the value of i. But you will have to wait for 2 seconds before being able to print again.

Do something in a few seconds time

If you want something to happen a couple of seconds after something else then you can just use Invoke.   Write a function containing the script you want to run, then call Invoke("NameOfYourFunction", delayInSeconds). In the example below, the TurnMeBlue function is called after 2 seconds.

function Start()
{
      //Turn the object blue in 2 seconds
      Invoke("TurnMeBlue", 2);
}

function TurnMeBlue()
{
       renderer.material.color = Color.blue;
}

You might even want to use multiple invokes to make things happen in a sequence:

var startPosition : Vector3;
var health = 100.0;
var respawning = false;

function Start()
{
    //Cache were this object started
    startPosition = transform.position;
}

//Reset the object
function Respawn()
{
      transform.position = startPosition;
      health = 100;
      renderer.enabled = true;
      respawning = false;
}

//Hide the character
function Hide()
{
     renderer.enabled = false;
     transform.position = new Vector3(1000,1000,1000);
}

function Update()
{
    if(health < 0 && !respawning)
    {
         respawning = true;
         animation.Play("die");
         Invoke("Hide", 3);
         Invoke("Respawn", 10);
    }
}

This script uses invoke to play a death animation and then respawn the character.  When the health drops below 0 a "die" animation is played.  The model is hidden (and moved out of the way) in 3 seconds and then respawned in 10 seconds.

Do something every few seconds

Rather than writing a coroutine with a loop you can simply write a function that contains the script you want and use InvokeRepeating("YourFunctionName", delayForFirstCall, timeBetweenCalls).

You can always cancel this using CancelInvoke("YourFunctionName") or without any parameters to cancel all of them.

float health = 100f;

void Start()
{
    InvokeRepeating("Heal", 2, 2);
}

void Heal()
{
    health = Mathf.Clamp(health + 1, 0, 100);
}
Note that at the time of writing, InvokeRepeating has a little bug on the second parameter. If you want to get the first call right on Start you might want to give a value of 0. In this case, the first call happens twice. To fix this issue, simply give a value of 0.01f.

When to use a coroutine

A coroutine can be useful when you need something that would otherwise be in an Update call and you don't want to make Update too complicated.

Be aware that having Update and multiple coroutines all changing the same variables is the source of hard to spot errors.

For example you might want to rotate an object to a new angle over time.  This could be a use for a coroutine.  In the following example calling RotateBy rotates the object to a new angle over a period of time.

function OnMouseUp()
{
     RotateBy(Vector3(0,90,0),2);
}

function RotateBy(angle : Vector3, time : float)
{
     var currentRotation = transform.rotation;
     var targetAngle = currentRotation.eulerAngles + angle;
     var targetRotation = Quaternion.Euler(targetAngle);
     var t = 0;
     while(t < 1)
     {
          transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, t);
          t += Time.deltaTime / time;
          yield null;
     }  
     transform.rotation = targetRotation;
}
In Javascript you make a function a coroutine simply by adding a yield to it. Never do this in Update as its the one place this doesn't work.


How to move with Vector3.Lerp

How to move with Vector3.Lerp

You have your line of code but for some reasons nothing is happening or it all happens at once. Lerp is a interpolation between two points start and to by a ratio t.  So t <=0 the result is the start position and t >=1 then the result is the to position.

transform.position = Vector3.Lerp(start, to, t);

If you want to move between two points exactly in a set amount of time, then you need to record the starting position and increment t (usually by a factor of Time.deltaTime/NumberOfSecondsToComplete) and the object will reach the destination when t reaches 1.

Like this:

Vector3 _start;
Vector3 _target;
float _t;

void Update()
{
     transform.position = Vector3.Lerp(_start, _target, _t);
     _t += Time.deltaTime/2; //Take 2 seconds
}

public void SetTargetPosition(Vector3 newTargetPosition)
{
    _start = transform.position;
    _target = newTargetPosition;
    _t = 0;
}

Otherwise you might want a smoothed effect where you just move from where you currently are towards the target - in that case you use it differently and keep passing the current position as the first Lerp parameter.

In human words, it means you take the start(perhaps transform.position) and you look at to (the target.position). Then you move the object by the amount of t. If you give t= 1 it moves suddenly from start to to. If you give 0.5 it will move 1/2 of the current distance between the two points each frame.

function Update(){
    transform.position = Vector3.Lerp(transform.position, target.position, Time.deltaTime);
    }

If there would be 10 m between transform(0) and target(10) and deltaTime is 0.2 (20%) then you get:

  1. 20% of target-transform (10-0) = 2m so transform = 2
  2. 20% of target-transform (10-2) = 1.6m so transform = 3.6
  3. 20% of target-transform (10-3.6) = 1.28m so transform = 4.88
  4. And so on

Note that the object will never really get exactly to its destination but more likely get really close, similarly to the limit principle in algebra.

Some examples use Time.time as ratio. This is somehow wrong as your interpolation would only happen in the first second of your scene. Give a value between 0 and 1 considering that 0 will not move at all and 1 will move it all at once, so 0 < t < 1.


How to store lists of objects that can grow

How to store lists of objects that can grow

Don't use Array, ArrayList and HashTable - you should always use one of the .NET generic collections or built in arrays.  The old fashioned collections mean you have to type lots of code to get the object type you want out of them, generic collections remove that problem and can still be made to contain many different types of object if you really need to.
Built in arrays, like int[100], are the fastest and most efficient collections, but you can't grow or shrink them at runtime.  Use them if you don't need your array to change its shape

In C# you need to add:

using System.Collections.Generic;

To the top of your source file to use the generic collections.  There is no such requirement for Javascript.

Instead of using Array or ArrayList use generic Lists.  Lists can have items added or removed at runtime, they contain a specific type (or a subclass of that type), they can also be sorted easily and turned into arrays when necessary.

You can use the .NET documentation for List and Dictionary on MSDN.  Simple examples in Unity Script and C# are shown below and should give you the general idea.

You work with Lists like this:

//Define a list using Javascript
var myList = new List.<int>(); 
var anotherList = new List.<SomeClass>();

//Define a list using C#
List<int> myList = new List<int>();
List<SomeClass> anotherList = new List<SomeClass>();

//Add element to a list
myList.Add(someValue);

//Add multiple elements to a list
myList.AddRange(someListOrArrayOfValues);

//Clear all elements
myList.Clear();

//Insert into a list
myList.Insert(1, someValue);

//Insert multiple elements
myList.InsertRange(1, someListOrArrayOfValues);

//Remove a specific value
myList.Remove(someValue);

//Remove at a specific index
myList.RemoveAt(1);

//Find an index of an element
var index = myList.IndexOf(someValue);

//Find an index of something using a function in Javascript
var index = anotherList.FindIndex(function(entry) entry.someValue == something);

//Turn a list into an array
var myArray = myList.ToArray();

//Find an index of something using a function in C#
var index = anotherList.FindIndex((entry) => entry.someValue == something)

//Get the number of items in the list
var itemCount = myList.Count

Dictionaries are the .NET generic associative arrays you work with Dictionaries like this:

//Define of a string to an int in Javascript
var myDic = new Dictionary.<String, int>();

//Define a dictionary of GameObject to a class in Javascript
var anotherDic = new Dictionary.<GameObject, SomeClass>();

//Define a string to int dictionary in C#
Dictionary<string, int> myDic = new Dictionary<string, int>();

//Define a dictionary of GameObject to a class in C#
Dictionary<GameObject, SomeClass> anotherDic = new Dictionary<GameObject, SomeClass>();

//Add an element to a dictionary
myDic["Something"] = someIntValue;

//Get a value from a dictionary
var someValue = myDic["Something"];

//Get a complex value and change one of its properties
anotherDic[gameObject].someProperty = someValue;

//Check if a value exists
if(myDic.ContainsKey("Something")) { }

//Remove an element from a dictionary
myDic.Remove("Something');

//Run through all of the keys in the dictionary JS
for(var key : String in myDic.Keys) { }

//Run through all of the values in the dictionary in C#
foreach(int value in myDic.Values) { }

//Clear all elements
myDic.Clear();

//Get the number of items in the dictionary
var count = myDic.Count;


How to configure and move rigidbodies

How to configure and move rigidbodies

Physics is your friend, it will simulate lots of things for you, but you have to treat it right!

If you are using the physics system you should use AddForce or the like to move rigidbodies unless they are kinematic.
If you move rigidbodies yourself you must do it in FixedUpdate, but still expect unusual behaviours such as unexpectedly large or small forces being applied to other objects.

You cannot use Input functions in FixedUpdate.  If you must get user input, you will need to get it in Update and apply it in FixedUpdate.

Do not change gravity or timescale, if things appear to be moving too quickly or too slowly then the objects are probably not the right size/distance away from the camera, fixing the effect by changing gravity will often cause lots of unexpected errors.  Don't do it if you are a beginner, get the scale and proportions right.
Use realistic sizes for objects.  Treat 1 world unit as 1 metre, always.  A person is 1.7 metres high, a car is 3.5 metres long etc etc.  Get the sizes right, get the camera the right distance away and you will get the effects you want.  If in doubt examine things in the real world and see how they interact.

If your "ball" appears to drop too quickly have you made it the size of a marble?  Try dropping a marble onto your desk - see how fast it moves?  If you were looking for a more "floating" effect you need a much bigger ball, much further away.


What the CharacterController is for

What the CharacterController is for

Character Controller is designed for both the player and NPC characters in a running around and shooting game.  Character Controllers are great for this, they cover a lot of the complicated logic concerning moving platforms, characters blocking other characters etc.

Forget using a character controller if you want Physics to affect your object.  You need to build your own scripts.

Many games just don't lend themselves to using a Character Controller - so just be sure that is what you want before you commit to it - if you do use it, only use it on the things you need it on.

You can have a Character Controller affect physical objects, for example to push them out of the way.  You need to add some script for that and you cannot always guarantee that it will look realistic as you are interfering with the Physics system when you do this.  See this example.
Be aware that character controllers don't have rigidbodies by default and so OnCollisionXXXX and OnTriggerXXXX methods aren't called by default.  You can add a kinematic rigidbody or handle OnControllerColliderHit.
Always use SimpleMove or Move to move an object that uses a Character Controller.  Do not update the position directly.


How to modify the rotation of an object using Quaternions | Don't change x,y,z!

How to modify the rotation of an object using Quaternions

The x,y,z,w parameters of a quaternion are nothing to do with the values you see in the inspector for the rotation of an object.  The x,y,z,w variables are not stored in degrees (they are sines and cosines of angles). The rotations in degrees are stored in the .eulerAngles of the rotation.

You should not modify x,y,z,w of a Quaternion unless you really know what you are doing.  If you want to change the rotation of something using degrees then modify the .eulerAngles.

If you want to understand Quaternions in detail then it's a big subject.  See this tutorial.

To set the angles of an object as seen in the inspector do this:

transform.rotation.eulerAngles = new Vector3(100,0,100);


How to access C# script from Javascript or vice versa

You need to access a C# script from Javascript or vice versa

You can only ever get this access to work in one direction, accessing a Javascript class from a C# file or vice versa.  You can never get two classes to interact with each other in two directions if they are written in two different languages.
Choose one language to write your project in.  If you use 3rd party components that will be completely independent then it doesn't matter what language they are written in, so long as you put them in one of the locations that is compiled first - Standard Assets, Pro Standard Assets or Plugins and you access them using code that isn't under one of those special locations.

Javascript and C# are not compiled into the same assembly so you can't just easily refer to one from the other.  Any code in Plugins, Standard Assets or Pro Standard Assets will be compiled first and so code that isn't in those directories will have access to all of the scripts and classes that were defined in them.

In this way you can make a C# script access Javascript classes, by putting the Javascript in Standard Assets, Pro Standard Assets or Plugins (or any folder beneath them).  You can make a Javascript script access C# classes by putting the C# classes in a folder beneath Standard Assets, Pro Standard Assets or Plugins.  Remember that Javascript in one of the special folders cannot access C# in any folder and C# in a special folder cannot access Javascript classes no matter where they are.  This is why you shouldn't try to mix languages in your own project, if you suddenly need access to something you may find that there is no way to get it.

Unity has some good documentation on script compilation order that you can find here.


You think you are programming Unity in Java or Javascript

You think you are programming in Java or Javascript with Unity

Firstly Unity says it uses Javascript.  Javascript is not Java, it is not related to Java and only has a few high level similarities.  When Javascript was written it was originally called LiveScript.  Java was popular at the time and it was renamed to make it sound more relevant.
If you are a Java programmer you will find that C# is closer to Java than Unity Javascript. There are many tutorials on moving from Java to C# and they are all totally relevant to C# in Unity.
Javascript in Unity is not Javascript.  Many of us call it Unity Script to make that differentiation.  Javascript in Unity is a .NET language more closely related to Action Script than it is to Javascript.  It has a number of features of Javascript, but many are missing.  It uses classical inheritance rather than prototypical inheritance, you can't add functions to objects after compilation, the list goes on and on.
Under no circumstances do a real Javascript tutorial or read a real Javascript book and try to apply it to Unity.  You will just end up confused.


Your coroutine doesn't finish after a wait or yield

Your coroutine doesn't seem to finish after a wait or yield

This often happens because you have disabled the script containing the coroutine or destroyed the object that the script lives on.  Often when you kill something you want to start a coroutine or use an Invoke to have something happen after a dying animation, a score update or some other delayed process.

Coroutines will execute immediately up to the first yield instruction - so the first part will always run.  If you disable your script or destroy your object the rest of the routine will never execute.
If you use WaitForSeconds then the Time.timeScale must be greater than 0 or your yield will never return.  Remember WaitForSeconds uses game time which is affected by timeScale.
Coroutines run on the object that StartCoroutine is called on.  So if you are starting a coroutine on a different object it makes a lot of sense to use StartCoroutine on that object, not the one you are currently executing.  E.g. otherScript.StartCoroutine(otherScript.SomeFunction());

The wrong way to write a coroutine:

void Update() {
    if(health < 0) { 
           StartCoroutine(Die()); 
           Destroy(gameObject); //or enabled = false; 
    } 
} 

IEnumerator Die() { 
       animation.Play("wobble"); 
       yield return new WaitForSeconds(3); 
       //This will never be called 
       animation.Play("die"); 
}

The correct way to write that script would be:

bool dying; 
void Update() { 
     if(dying) return; 
     if(health < 0) { 
         StartCoroutine(Die()); 
     } 
} 

IEnumerator Die() { 
      dying = true; 
      animation.Play("wobble"); 
      yield return new WaitForSeconds(3); 
      animation.Play("die"); 
      yield return new WaitForSeconds(3); 
      Destroy(gameObject); 
}

, , , , , , ,

33 Responses to "Common Unity Gotchas"

  • Javier Roman
    October 21, 2012 - 4:54 pm Reply

    You answered some nagging questions in such a clear way. I am grateful. You need to write a Gems book! I would pre-order that! Hope you have time to post some more. (It’s funny, I’ve only ever used C# from the beginning, seems like the javascript syntax creates more problems for people despite the “ease” it should offer.)

    Keep up the good work and thanks again.

    -JR

  • ArcIo
    November 10, 2012 - 6:40 pm Reply

    Wow. Simply wow. I wish I found this like 3 months ago.

  • steph
    December 1, 2012 - 11:07 pm Reply

    I think this is the best c# Unity tutorial site found on the internet!

    Thank you for taking the time to help people learn and understand quickly!!

  • yuanym1111
    December 4, 2012 - 9:54 am Reply

    I think if I can translate all you articles to Chinese. All these things are great!

  • Tinyutopia
    December 10, 2012 - 2:02 am Reply

    This information helped me a great deal. Thanks for taking the time to write and post it!

  • Singh
    January 31, 2013 - 5:47 am Reply

    Rigidbody,how does that work – Cant download the project. New link please.

    • fafase
      January 31, 2013 - 7:24 pm Reply

      For some reason the server I was keeping the files has simply emptied my files…I will try to get in touch with them and see why they did so. In the meanwhile do not use 000webhost.com.

  • Singh
    February 1, 2013 - 1:05 pm Reply

    Thanks for reply. Any chance of getting that project or a similar project. Thanks.

    • fafase
      February 2, 2013 - 7:24 am Reply

      The server claims some weak reasons for removing the files so I will try and come up with a new one within next week.
      Fafase

      P.S. : Definitely do not use 000webhost.com

  • bunt
    February 19, 2013 - 8:59 am Reply

    You should do one about world space… that just did my head in…

  • Num_T
    March 30, 2013 - 4:47 pm Reply

    I could be being stupid…. but….. in the last example why is there a function call RotateBy() and then a function called RotateTo()? Is it just a typo? I’d love to know how you would do this in C# as well as I am really struggling with picking one or ‘tother!

  • whydoidoit
    March 31, 2013 - 4:31 pm Reply
    
    void OnMouseUp()
    {
         StartCoroutine(RotateBy(new Vector3(0,90,0),2));
    }
     
    IEnumerator RotateBy(Vector3 angle, float time)
    {
         var currentRotation = transform.rotation;
         var targetAngle = currentRotation.eulerAngles + angle;
         var targetRotation = Quaternion.Euler(targetAngle);
         var t = 0f;
         while(t < 1)
         {
              transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, t);
              t += Time.deltaTime / time;
              yield return null;
         }  
         transform.rotation = targetRotation;
    }
    
  • whydoidoit
    March 31, 2013 - 4:34 pm Reply

    And yep – it was a typo! Fixed now…

    • Num_T
      March 31, 2013 - 4:36 pm Reply

      Awesome! Many thanks and congrats on a great site by the way.

  • gamesonytablet
    April 2, 2013 - 3:48 am Reply

    Gees, this is so awesome how you summarize so good!

    BTW, are you saying that Array, ArrayList and HashTable should never be used (period!) or do you think there may be a limited situation, if used correctly?

    • fafase
      June 11, 2013 - 6:20 am Reply

      Array yes to be used even though you can do pretty much the same thing with List without too much of a penalty. If you have a collection of objects of which you know how many from start and it wont change, then use array.

      ArrayList no, because they are typeless. As a result you need to cast everything you do which is slow and if you remove an item out of list of different object types, you are lost. You may have a list for each type instead.

      As for hashtables, you have the same but better with Dictionaries.

  • 西伯利亚野猪
    April 19, 2013 - 7:41 am Reply

    Great work! Thank you!

  • chandra
    May 14, 2013 - 7:25 am Reply

    First i would like to say thanks. Because this is the only place where i can get the detailed and proper information. I appreciate your work please keep up the same.

  • Ash McConnell
    June 8, 2013 - 4:35 pm Reply

    Thanks for a great list of mistakes! I am still having trouble with the collisions between 2 Kinematic RBs. I want to be able to use the collision data in our custom built car physics engine, but I can’t get enough information about collisions to pass to the engine (I want to bypass Unity’s physics engine entirely).

    Is it possible to do what I’m trying to?

  • luniac
    July 18, 2013 - 9:55 pm Reply

    What unexpected errors can i expect if i change gravity. I’ve doubled it in my game because of floaty falling rigidbody early in my game production almost a year ago. I have yet to see any problems that i can directly attribute to doubling the physics constant.

    I HAVE made friction and air drag adjustment to my rigidbody accordingly though…

    • Num_T
      July 26, 2013 - 6:30 pm Reply

      I am a loooooong way from an expert on rigidbodies but my understanding is that if your behaviour doesn’t seem right it’s probably because your scale is way off. No idea if it’s *safe* to counter act this by tweaking values though…

      • luniac
        July 26, 2013 - 6:56 pm Reply

        yea my scale was too large i suspect, but thats why i doubled the physics constant because it would be too much work to change all my scales… seems fine..

        • fafase
          July 26, 2013 - 7:08 pm Reply

          It would be too much work to change all your scale but in the long run, it is less work.

          It would be way easier to set everything back to a “human” scale with 1 unit being 1m. That makes it easier because a character can be 2 units and mass 75/80. A car would then be 3 units long and mass 1000 and so on.

          My advice, take the time to set it all back to normal scale.

          Fafase

          • luniac
            July 26, 2013 - 7:46 pm

            Well in this case it really would be too much work since it’s been over a year that i doubled the gravity constant, i got many levels and many prefabs and all my physics options have been painstakingly adjusted to create smooth controls within the physics engine.

  • Halldor
    October 11, 2013 - 7:15 am Reply

    you are a god, i have been trying to figure out getComponent for ages, finally my script works thank you so mutch

  • PTTC
    December 11, 2013 - 12:02 pm Reply

    Fantastic series,
    Thanks.
    If you have the time keep adding to it, your work is useful and appreciated

  • Ian Deane
    January 13, 2014 - 10:03 pm Reply

    Great site. Useful information.

    You should add something about mesh vs. sharedMesh and material vs. sharedMaterial. In my opinion this is a VERY nasty part of the Unity API. It is very easy to write code that will leak meshes and materials by using the obvious “mesh” and “material” properties when developers should be using “sharedMesh” and “sharedMaterial”.

  • Leonardo Raele
    January 23, 2014 - 1:17 am Reply

    Thanks, you answered my question: How to access a variable or method on another script or object?

    Also, I found “How to access C# script from Javascript or vice versa” a very interesting topic. I’m sure I would fall in this question in the future.

  • Chris S
    April 9, 2014 - 1:25 am Reply

    Thank you soooo much!

    I couldn’t get animation working until I stumbled across this site and saw the gotcha on coroutines!

    Thank you!!

Leave a Reply

%d bloggers like this: