Here is the reading notes on Intermediate Gameplay Scripting
Intermediate Gameplay Scripting from Unity Toturials
Porperties
For public variables shared between scripts, a better way is to use properties.
1 | public class Example{ |
There are two advantages for this.
- You can omit either get or set to make the variable readonly or writeonly.
- You can regard the accessors as a funciton and do what you want in it.
For example:
1 | public class Example{ |
Ternary Operator
Can replace some simple IF statement.
1 | int i = 1; |
Generics
Generics is a feature where by classes and mothods among other things can be passed the type as a parameter. This in fact allows you to program generically without knowing the actual type.
Method Generics1
2
3
4
5public class Example(){
public T GenericsMethod(T param){
return T;
}
}
However, if you call a method of T which doesn’t belong to that type, an error will be given.
Therefore, we need to add some constraints to that type T.
Constraints can be:
- class: T is a class type
- struct: T is a value type
- new(): T has a construct funciton without parameters
- ClassName: T is that class or derived from that class
- InterfaceName: T has implements that interface
1 | public class Example(){ |
Interface
Interface allows you to realize common functionalities among multiple different classes.
An interface con contains signatures of the following members:
- Properties
- Methods
- Indexers
- Events
Which means you are not allowed to declare a variable (field) inside the interface.
All signatures inside interface should be realized in the class which implements that interface.
Interface1
2
3
4
5
6
7
8
9
10
11
12
13
14//This is a basic interface with a single required
//method.
public interface IKillable
{
void Kill();
}
//This is a generic interface where T is a placeholder
//for a data type that will be provided by the
//implementing class.
public interface IDamageable<T>
{
void Damage(T damageTaken);
}
Realize Interface1
2
3
4
5
6
7
8
9
10
11
12
13
14public class Avatar : MonoBehaviour, IKillable, IDamageable<float>
{
//The required method of the IKillable interface
public void Kill()
{
//Do something fun
}
//The required method of the IDamageable interface
public void Damage(float damageTaken)
{
//Do something fun
}
}
Why we use interface instead of polymorhism is that many times you would have two class which are not much related but have some common behaviours. For example, both a wall and a car should be damagable and destroyable. But they should not inherit from the same class. That’s why we use interface to realize the common behaviours.
Another reason for that is in C#, a class can only inherits from one class, but can implement multiple interfaces.
Extension Method
Extension method is used when you want to extent the functionalities of classes which is encapsulated in Unity and code-untouchable. You need to create a static class for that and use a “this” keyword to define the parameter.
Example
1 | public static class ExtensionMethods |
PS: It is common to create a class to contain all of your extension methods. This class must be static.
Namespace
Namespace is used to avoid ambiguity and conflict between scripts.
Chances are all the scriptsa you are writing so far are using namespaces. When you are using the “using” statement, it means you are using that namespace, and all classes in that namespace can be used on the script.
For example, Random is a class both in System and UnityEngine. To avoid ambiguity, you can use namespace as following format:
1 | System.Random rd1 = new System.Random(); |
To create your own namespace, you only need to use “namespace” statement with a brace, and write your class inside.
1 | namespace SampleNamespace |
Quaternion
Quaternion is used to represent rotations in Unity. It’s described by four properties x, y, z and w. However 99% of the time you are not suggested to directly change those values instead of using some useful functions provided by Quaternion.
public void Rotate(Vector3 eulerAngles, Space relativeTo = Space.Self);1
2
3
4
5
6
7
8
9public class MotionScript : MonoBehaviour
{
public float speed = 3f;
void Update ()
{
transform.Translate(-Input.GetAxis("Horizontal") * speed * Time.deltaTime, 0, 0);
}
}
public static Quaternion LookRotation(Vector3 forward, Vector3 upwards = Vector3.up);1
2
3
4
5
6
7
8
9
10public class LookAtScript : MonoBehaviour
{
public Transform target;
void Update ()
{
Vector3 relativePos = target.position - transform.position;
transform.rotation = Quaternion.LookRotation(relativePos);
}
}
public static Quaternion Slerp(Quaternion a, Quaternion b, float t);
Spherically interpolates between a and b by t. The parameter t is clamped to the range [0, 1].
1 | public class GravityScript : MonoBehaviour |
Event
Event is special delegate used when you want to alert other classes when something has happened.
Other reference: http://www.unitygeek.com/delegates-events-unity/
Example1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class EventManager : MonoBehaviour
{
public delegate void ClickAction();
public static event ClickAction OnClicked;
void OnGUI()
{
// Manually create a button
if(GUI.Button(new Rect(Screen.width / 2 - 50, 5, 100, 30), "Click"))
{
// Null reference should be checked here
if(OnClicked != null)
OnClicked();
}
}
}
public class TeleportScript : MonoBehaviour
{
void OnEnable()
{
EventManager.OnClicked += Teleport;
}
void OnDisable()
{
EventManager.OnClicked -= Teleport;
}
void Teleport()
{
Vector3 pos = transform.position;
pos.y = Random.Range(1.0f, 3.0f);
transform.position = pos;
}
}
Event should be defined public and static. It works like public delegate and there is something different.
Events adds a layer of abstraction and protection on delegate, this protection prevents client of the delegate from resetting the delegate and invocation list. Events only allow to add and remove method from invocation list.
Therefore, if you try to invoke or override an event defined in other class, an error will be given.
1 | public class InvokeExample : MonoBehaviour |
1 | Assets/TeleportScript.cs(10,16): error CS0070: The event `EventManager.OnClicked' can only appear on the left hand side of += or -= when used outside of the type `EventManager' |
Conclusion:
- Delegates and Events help us to write modular and reusable code.
- Always use Events together with Delegates for safety.
- Do not forget to unsubscribe otherwise, it will lead to memory leak.