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
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”
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 != null && col.rigidbody != this.gameObject.rigidbody)
{
col.rigidbody.AddExplosionForce (this.power, this._transform.position, this.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.
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.
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.
Other important considerations
There are a number of other rules that concern what things will make a collision occur.
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
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.
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
{
private bool action = false;
private void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
action = true;
}
}
private void FixedUpdate()
{
if(this.action == true)
{
//Action
this.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.
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 startposition and t >=1 then the result is the to position.
this.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:
private Vector3 start;
private Vector3 target;
private float t;
private void Update()
{
this.transform.position = Vector3.Lerp(this.start, this.target, t);
t += Time.deltaTime/2; //Take 2 seconds
}
public void SetTargetPosition(Vector3 newTargetPosition)
{
this.start = this.transform.position;
this.target = newTargetPosition;
this.t = 0f;
}
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 <em>start</em>(perhaps transform.position) and you look at <em>to</em>(the target.position). Then you move the object by the amount of t. If you give t= 1 it moves suddenly from <em>start</em> to <em>to</em>. If you give 0.5 it will move 1/2 of the current distance between the two points each frame.
private void Update()
{
this.transform.position = Vector3.Lerp(this.transform.position, this.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:
- 20% of target-transform (10-0) = 2m so transform = 2
- 20% of target-transform (10-2) = 1.6m so transform = 3.6
- 20% of target-transform (10-3.6) = 1.28m so transform = 4.88
- 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.
How to store lists of objects that can grow
In C# you need to add:
using System.Collections.Generic;
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 work with Lists like this:
//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:
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") == true) { }
//Remove an element from a dictionary
myDic.Remove("Something');
//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
Physics is your friend, it will simulate lots of things for you, but you have to treat it right!
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.
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.
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
If you want to understand Quaternions in detail then it’s a big subject.
To set the angles of an object as seen in the inspector do this:
this.transform.rotation.eulerAngles = new Vector3(100f,0f,100f);
You need to access a C# script from Javascript or vice versa
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.
You think you are programming in Java or Javascript with Unity
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.
The wrong way to write a coroutine:
private void Update()
{
if(this.health < 0)
{
StartCoroutine(Die());
Destroy(this.gameObject); //or enabled = false;
}
}
private 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:
private bool dying = false;
private void Update()
{
if(this.dying == true) { return; }
if(this.health < 0)
{
StartCoroutine(Die());
}
}
private IEnumerator Die()
{
this.dying = true;
animation.Play("wobble");
yield return new WaitForSeconds(3);
animation.Play("die");
yield return new WaitForSeconds(3);
Destroy(this.gameObject);
}


Really fantastic article!
I started with Unity game development a week ago, coming from an programming background. And as a beginner in Unity I already ran into some of the problems mentioned in the article. For example rotation with quaternions or that physical forces to rigidbodies only apply properly in the FixedUpdate() function.
This articles is a great help, thanks!
LikeLike