Professional Documents
Culture Documents
The Relevant Unitys Stuff
The Relevant Unitys Stuff
simonsanchezart.com/the-relevant-unity-stuff/2048
The objective of this post is to gather all the fundamental concepts that you and me could
want to check out if we get stuck in something. Things like how to loop over all the
elements in a dictionary, how to create an enum, the difference between const and
readonly and so on.
(The information here is not the most optimal or exact, it’s what I know at this point and
time and will be updated. For feedback, please leave a comment!)
Index
Executions
OnValidate()
Gets called when it gets loaded or when a value is changed in the inspector.
LateUpdate()
Executes after all the code inside Update() gets executed, useful when making, for example
a Camera Follow, as the camera needs to follow a character after this character was moved
in Update().
Awake()
Gets called even if the script is not enabled. (Before Start())
FixedUpdate() vs Update()
Update is called each frame, FixedUpdate is called every x physics step, FixedUpdate
should be used when manipulating physics or rigidbodies, specially if those manipulations
are over time and not single-framed.
Debugging
Formatted logs
1/45
1 Debug.LogFormat( "The age of {0} is {1}, it's {2} that he has a pet" ,
nameString, ageInt, petBool);
Pretty logs
Throwing exceptions
Try-catch
2/45
1 try
2 {
ValidateEmail( "ea" );
3 Debug.Log( "Email validated" );
4 }
5 catch (System.ArgumentException exceptionVariable)
6 {
7 Debug.Log( "Unsuccessful attempt, " +
8 exceptionVariable.ToString());
9 }
finally
10 {
11 Debug.Log( "Email validator ran" );
12 }
13
14
15
16
17
Syntax
Member naming
If’s
Switch statement
3/45
1 int caseSwitch = 1;
2 switch (caseSwitch)
3 {
4 case 1:
5 Console.WriteLine( "Case 1" );
break ;
6
case 2:
7
Console.WriteLine( "Case 2" );
8 break ;
9 default :
10 Console.WriteLine( "Default case" );
11 break ;
12 }
13
14
Fall-through
1 switch (values)
2 {
3 case Numbers.x:
4 case Numbers.x1:
5 print( "For both x and
x1" );
6 break ;
7 case Numbers.y:
8 case Numbers.y1:
9 print( "For both y and
10 y1" );
11 break ;
12 }
Ranges in Switch
4/45
1 int age = 25;
2 switch (age)
3 {
4 case int n when (n >= 18 && n
5 <=25):
print( "You're between 18 and 25" );
6
break ;
7 default :
8 print( "You're older than 25" );
9 break ;
10 }
11
12
Ternary operator
Loops
For loop
Do-while loop
Runs at least once, then checks if the condition is true to run again.
5/45
1 int i = 0;
2 do
3 {
print(i);
4
i++;
5 } while (i < 50);
6
7
While loop
Break
Used to stop a loop.
Continue
Instead of stopping the loop completely, stops the current iteration (based on a condition.)
Nested loops
Methods
Return type
7/45
1 [SerializeField] int total;
2 void Start()
3 {
4 total = Sum(1, 1);
}
5
int Sum( int a, int b)
6 {
7 return a + b;
8 }
9
10
11
12
13
Method overriding
1 void Start()
2 {
3 Invoke(nameof(DebugTest), 1f);
}
4
void DebugTest()
5 {
6 Debug.Log( "No strings
7 attached" );
8 }
9
10
11
12
13
Method overloading
Extension methods
9/45
1 public static class ExtensionMethods
2 {
3 public static void ResetTransform( this Transform
4 trans)
{
5 trans.position = Vector3.zero;
6 trans.localRotation = Quaternion.identity;
7 }
8 }
9
Arrays
1 string [] names;
2 string [] names = new string [5];
3 string [] names = new string [] { "Jonathan" , "Simon" , "Alicia" ,
4 "Lila" };
5
Lists
Add an element
1 list.Add(element)
2
10/45
Insert element at x index
1 list.Insert(1, "George" );
2
3
Enums
11/45
1 enum Example = { Alive, Tired, Dead };
2 enum Example = { Alive = 2, Tired, Dead };
3 enum Example = { Alive = 5, Tired = 13, Dead = 2
4 };
5 enum Example : byte = { Alive, Tired, Dead };
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1 enum Difficulty
2 {
3 Easy,
Normal,
4
Hard
5 }
6 [SerializeField] Difficulty selectedDifficulty;
7 void Start()
8 {
9 SceneManager.LoadScene(( int )selectedDifficulty);
10 }
11
12
13
14
Dictionaries
12/45
1 public Dictionary< int , Item> itemDatabase = new Dictionary< int ,
2 Item>();
3 void Start()
4 {
5 Item sword = new Item();
sword.name = "Sword" ;
6 sword.id = 0;
7 Item bread = new Item();
8 bread.name = "Bread" ;
9 bread.id = 0;
10 itemDatabase.Add(0, sword);
11 itemDatabase.Add(1, bread);
}
12
13
14
15
16
17
18
19
1 void Start()
2 {
3 var value =
4 students[ "Juan" ];
print(value);
5 }
6
13/45
1 var key = students.FirstOrDefault(s => s.Value ==
2 15).Key;
3 print(key);
4 var secondKey = ( from s
5 in students
6 where s.Value == 14
7 select s).FirstOrDefault().Key;
print(secondKey);
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1 Dictionary< string , int > students = new Dictionary< string , int >()
2 {
3 { "Juan" , 14},
{ "Matilda" , 21},
4 { "Romero" , 18}
5 };
6
7
14/45
1 [System.Serializable]
2 public class Item
3 {
4 public int itemID;
5 public string name;
6 public string description;
}
7
public class array : MonoBehaviour
8
{
9 public Item[] myItems;
10 void Update()
11 {
12 if (Input.GetKeyDown(KeyCode.Space))
13 {
14 foreach ( var item in myItems)
15 {
16 print(item.itemID);
17 print(item.name);
print(item.description);
18 }
19 }
20 }
21 }
22
23
24
25
26
27
Class Inheritance
1 [System.Serializable]
2 public class Items
3 {
4 public string name;
5 public int index;
6 public string description;
7 public Sprite image;
}
8
9
10
11
12
13
15/45
1 [System.Serializable]
2 public class Weapons : Items
3 {
4 public int damage;
5 public int bleed;
}
6
1 [System.Serializable]
2 public class Consumables : Items
3 {
4 public int health;
5 public int poison;
}
6
16/45
Abstract classes
They cannot be instantiated by themselves, and they can force the declaration of methods
to the classes that implement them.
17/45
1 public class Fulltime : Employee
2 {
3 [SerializeField] int earnedPerDay;
4 void Start()
5 {
CalculateMonthlySalary();
6 }
7 public override void CalculateMonthlySalary()
8 {
9 Debug.Log(employeeName + " will earn: $" + earnedPerDay *
10 24);
11 }
12 }
13
14
Interfaces
18/45
1 public class Player : MonoBehaviour,
2 IDamageable< int >
3 {
4 int IDamageable.health { get ; set ; }
5 void IDamageable.TakeDamage( int damageAmount)
{
6 }
7
8
9
10
Const vs readonly
Ref Keyword
To pass arguments as reference instead of value in methods, they need to be initialized
before being passed into the method, properties with get and set can’t be used as ref.
You’re not obligated to update the reference parameter.
Out keyword
Same as ref, but arguments don’t need to be initialized before passing into the method, but
you need to initialize the parameter before returning the method.
19/45
1 public static string UpdateDeathCount( out int countReference)
2 {
3 countReference = 1;
countReference++;
4
return "Next time you'll be at number " + countReference;
5 }
6 public static void DebugDeath()
7 {
8 Debug.Log( "Player deaths: " + playerDeaths);
9 string message = UpdateDeathCount( out playerDeaths);
10 Debug.Log( "Player deaths: " + playerDeaths);
11 }
12
13
14
15
16
Singleton pattern
Useful in cases you only have one instance of a class, for example in managers.
20/45
1 static GameManager _instance;
2 public static GameManager Instance
3 {
4 get
{
5 if (_instance == null )
6 {
7 Debug.LogError( "There's in no GameManager
8 instance" );
9 }
10 return _instance;
}
11
}
12 void Awake()
13 {
14 _instance = this ;
15 }
16 public void MethodExample( string text)
17 {
18 Debug.Log(text);
}
19
20
21
22
23
24
25
26
27
28
29
1 void Start()
2 {
3 GameManager.Instance.MethodExample( "This is a
test" );
4 }
Lazy Instantiation
21/45
1 get
2 {
if (_instance == null )
3
{
4 GameObject go = new
5 GameObject( "SpawnManager" );
6 go.AddComponent<SpawnManager>();
7 }
8 return _instance;
}
9
10
11
12
13
The disadvantage of lazy Instantiation is that you will need to find a way to dynamically
populate fields in the class if you’re instantiating the manager.
Non-Monobehavior Singleton
22/45
1 void Update()
2 {
3 if (Input.GetMouseButtonDown(0))
4 {
Ray rayOrigin = Camera.main.ScreenPointToRay(Input.mousePosition);
5 RaycastHit hit;
6 if (Physics.Raycast(rayOrigin, out hit))
7 {
8 IDamageable obj = hit.collider.GetComponent<IDamageable>();
9 if (obj != null )
10 {
11 obj.TakeDamage(509);
}
12
}
13 }
14 }
15
16
17
18
19
20
21
22
Delegates
Events
24/45
1 public delegate void ActionClick();
2 public static event ActionClick
3 onClick;
4 public void ButtonClick()
5 {
if (onClick != null )
6 {
7 onClick();
8 }
9 }
10
11
12
13
14
1 void OnEnable()
2 {
3 Main.onClick += TurnRed;
}
4
public void TurnRed()
5 {
6 GetComponent<MeshRenderer>().material.color = Color.red;
7 }
8 void OnDisable()
9 {
10 Main.onClick -= TurnRed;
11 }
12
13
14
15
16
17
Actions
1 using System;
2 public class Actions : MonoBehaviour
3 {
4 public static Action< int > OnDamageReceived;
5
6
7
8
9
10
25/45
Func
Lambda expressions
26/45
1 public Action< int , int >
2 Sum;
3 void Start()
4 {
Sum = (a, b) =>
5 {
6 int total = a + b;
7 Debug.Log(total);
8 };
9 Sum(2, 2);
10 }
11
12
13
14
15
27/45
1 public Func< int , int , int >
2 Sum;
3 void Start()
4 {
Sum = (a, b) =>
5
{
6 return a + b;
7 };
8 int total = Sum(5,5);
9 Debug.Log(total);
10 }
11
12
13
14
15
16
Protected
They’re only accessible to the same class and the classes who inherit from that class.
The difference between protected and private, is that protected allows classes to inherit
and access those variables.
Static
They’re shared with all instances of a class, static variables can be accessed without
instantiating an object of the class, if you change a static variable in one class, it will
change in all of the others.
28/45
1 void Update()
2 {
3 if (Input.GetKeyDown(KeyCode.Space))
4 {
UtilityHelper.CreateCube();
5 }
6 if (Input.GetKeyDown(KeyCode.E))
7 {
8 UtilityHelper.SetPositionZero( this .gameObject);
9 }
10 }
11
12
Properties
They can be read (get) only, write (set) only, or both, they can be accessed as public, at the
same time, you can make them run code when you read or write a property. You cannot
initialize them, you cannot see them in inspector (unless you’re in debug mode.)
1 bool isGameOver
2 public bool IsGameOver
3 {
4 get
{
5
return isGameOver;
6 }
7 set
8 {
9 isGameOver = value;
10 }
}
11
12
13
14
15
Namespaces
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
Useful to organize code, and to avoid conflicts when you have two classes with the same
29/45
name.
1 namespace WeaponPack.Magic
2 {
3 public class Weapon : MonoBehaviour
4 {
}
5 }
6
7
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using WeaponPack.Magic;
5 public class Weapon : MonoBehaviour
6 {
7 }
8
9
Vectors
A vector is a struct that stores three variables (x,y,z), it has a direction and a magnitude.
Vector2(-4, 3)
Magnitude of that vector = sqrt((-4)^2 + 3^2)
Magnitude = 5
To keep the direction of the vector, but with magnitude of 1, you need to normalize it:
Vector2(-4, 3)
magnitudeOfTheVector = 5
x1 = -4 / magnitudeOfTheVector
y1 = 3 / magnitudeOfTheVector
30/45
VectorC = VectorB – VectorA
You can get the distance between VectorA to VectorB by calculating the magnitude of
VectorC. And you can get the direction from VectorA to VectorB by normalizing VectorC.
Raycasting
31/45
Important stuff
For a Layer Mask to work properly when Raycasting, you need to assign also a
maxDistance, this is because the layer mask is treated as an int, therefore Unity can
mistakenly use the layer mask as a max distance, to set an infinite max distance, use
Mathf.Infinity.
Angles n’ stuff
32/45
33/45
34/45
Vector math
35/45
Lerp
1 Light _light;
2 void Start()
3 {
_light = GetComponent<Light>();
4 }
5 void Update()
6 {
7 _light.intensity = Mathf.Lerp(_light.intensity, 8f, 0.5f *
8 Time.deltaTime);
9 }
10
11
12
13
14
Input
GetKey
36/45
1 if (Input.GetKeyDown(KeyCode.Space))
2 {
3 print( "Space has been pressed" );
}
4
if (Input.GetKey(KeyCode.Space))
5 {
6 print( "Space is being pressed" );
7 }
8 if (Input.GetKeyUp(KeyCode.Space))
9 {
10 print( "Space has been released" );
}
11
12
13
14
15
16
17
Transform manipulation
Assign position
Using Axis
37/45
1 float speed = 5f;
2 void Update()
3 {
4 float horizontalAxis = Input.GetAxis( "Horizontal" );
5 float verticalAxis = Input.GetAxis( "Vertical" );
6 transform.Translate( new Vector3(horizontalAxis, verticalAxis, 0) * speed *
7 Time.deltaTime);
}
8
9
10
11
12
13
Time
Pause (Time.timeScale)
1 bool isPaused;
2 void Update()
3 {
4 if (Input.GetKeyDown(KeyCode.Space))
5 {
isPaused = !isPaused;
6 Time.timeScale = isPaused ? 0 : 1;
7 }
8 }
9
10
11
12
13
Linq
Contains
38/45
1 using System.Linq;
2 public class UsingLinq : MonoBehaviour
3 {
4 public string [] names = { "jon" , "marcos" , "aurelio" };
5 void Start()
6 {
7 bool nameFound = names.Any(name => name ==
"aurelio" );
8
Debug.Log( "Name found: " + nameFound);
9 }
10 void Start()
11 {
12 bool nameFound = names.Contains( "jon" );
13 Debug.Log( "Name found: " + nameFound);
14 }
15
16
17
18
19
20
21
22
23
Distinct
Where
39/45
1 void Start()
2 {
3 var longNames = names.Where(name => name.Length >
4 5);
5 foreach ( string name in longNames)
{
6 print(name);
7 }
8 }
9
10
Order
Query syntax
1 var scoreQuerySyntax =
2 from score in scores
3 where score > 80
4 select score;
5 var scoreQuery = scores.Where(score => score >
6 80);
7
8
9
Attributes
[Range(x, y)] – Before a variable to get a slider. (min, max)
40/45
[HideInInspector] – Hides variable in Inspector
[Multiline] – Similar to TextArea but places the text box at the right side of the label.
Context menu: the contextual menu is the menu that appears generally when right clicking.
Class Attributes
[DisallowMultipleComponent] – You cannot add two of the same class to the same
game object.
[ExecuteInEditMode] – Executes the code in the class without the need of playing.
[SelectionBase] – If added for example to a class attached to the parent, it selects the
parent in Scene View instead of the children.
Other Attributes
[UnityEditor.MenuItem(“Menu/Sub menu/Sub menu”)] – Adds a button in
Unity’s menu so you can call a method, this attribute needs to be added before the method.
Other
Saving data
PlayerPrefs: Stores and accesses data between game sessions, in Windows it’s stored in the
registry (where it’s stored depends on the Game name and Company name set up in Project
Settings)
41/45
1 [SerializeField] int number = 10;
2 [SerializeField] string name = "simon" ;
3 void OnValidate()
4 {
5 PlayerPrefs.SetInt( "Saved int" , number);
PlayerPrefs.SetString( "Saved string" , name);
6 PlayerPrefs.Save();
7 }
8
9
number was changed to 12 in the inspector, and name was changed to ‘test’
Json
42/45
1 [SerializeField] int number = 10;
2 [SerializeField] string nametest = "simon" ;
3 [SerializeField] Color color;
4 [SerializeField] AnimationCurve curve;
5 void OnEnable()
{
6
JsonUtility.FromJsonOverwrite(PlayerPrefs.GetString( "json file" ), this );
7 }
8 void OnDisable()
9 {
10 PlayerPrefs.SetString( "json file" , JsonUtility.ToJson( this , true ));
11 PlayerPrefs.Save();
}
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
43/45
Optimization tips
Code for readability first, profile, and then optimize.
You can use Samples to make things more clear in the Profiler
44/45
1 using UnityEngine.Profiling;
2 public class MyClass: MonoBehaviour
3 {
4 void Update()
5 {
Profiler.BeginSample( "DEBUGING" );
6 Debug.Log( "object destroyed" );
7 Profiler.EndSample();
8 }
9 }
10
11
12
13
Share this
45/45