2.4 Functions and Methods in C# For Unity
2.4 Functions and Methods in C# For Unity
GAME PROGRAMMING
C# PROGRAMMING AND UNITY
2
Methods in Unity
Some Unity-specific methods commonly used in C# scripts:
1. Awake() and Start()
Awake()
Called when the script instance is being loaded
It's used for initializing variables or setting up references before Start()
Start()
Called once per frame when the script is enabled, after Awake()
It's typically used for initializing variables or setting up references
2. Update()
Called once per frame
It's often used for game logic that needs to be updated continuously, like
character movement or input processing
3
Methods in Unity
3. FixedUpdate()
Called at a fixed time interval, typically used for physics-related calculations
It's more reliable for physics operations than Update()
4. OnEnable() and OnDisable()
OnEnable(): Called when the object becomes enabled and active
OnDisable(): Called when the object becomes disabled
5. LateUpdate()
Called once per frame after Update()
It's often used for camera-related operations to ensure that all Update()
operations have been completed
4
Coroutine
A coroutine is a special type of routine or subroutine in computer
programming that allows for non-blocking execution. Unlike regular
functions or methods, coroutines can be paused and resumed, allowing the
program to perform other tasks while waiting for a particular operation to
complete
Coroutines are often used in scenarios where asynchronous or time-
consuming operations need to be performed without freezing the entire
program
Coroutines are commonly used in game development, and Unity, a popular
game development engine, has a coroutine system as part of its scripting
API. In Unity, coroutines are used to handle tasks such as animations,
delays, and other operations that may take time but should not block the
main thread
5
Coroutine
The concept of coroutines is not limited to Unity; it exists in various
programming languages and frameworks
Coroutines can simplify asynchronous programming by providing a more
readable and structured way to manage asynchronous tasks compared to
using callbacks or threads. They are particularly useful in scenarios where
you want to avoid the complexity and potential issues associated with
multithreading
6
Coroutine
Delaying
Execution
7
Coroutine
Animating
Objects
8
Coroutine
Loading Scenes
asynchronously
9
Coroutine
To use coroutines in Unity, you can follow these steps:
1. Write a Coroutine Function:
Create a function with the return type IEnumerator and use the yield
return statement to specify the points at which the coroutine should pause
and resume
Here's a simple example:
10
Coroutine
2. Start the Coroutine:
Use the StartCoroutine method to initiate the coroutine
You typically call this method from the Start or Update functions, or in
response to an event
11
Coroutine
3. Handle Coroutine Completion (Optional):
If you need to perform actions after the coroutine completes, you might want
to consider using a callback or checking a flag within the coroutine
12
Coroutine
4. Stop Coroutine (Optional):
If you need to stop a running coroutine prematurely, you can use the
StopCoroutine method and pass in the reference to the coroutine
13
Generic Functions
Some functions in the script reference (for example, the various
GetComponent functions) are listed with a variant that has a letter T or a
type name in angle brackets after the function name:
These are known as generic functions. The significance they have for
scripting is that you get to specify the types of parameters and/or the return
type when you call the function
14
Generic Functions
In JavaScript, this can be used to get around the limitations of dynamic
typing:
15
using UnityEngine;
17
Event Functions
In Unity, a script doesn't run continuously like a traditional program.
Instead, Unity intermittently passes control to the script by calling specific
functions declared within it, known as event functions
These functions respond to gameplay events, and Unity identifies them
through a naming scheme. Examples include the Update function (before
a frame update) and the Start function (before an object's first frame
update)
Many more event functions exist, detailed in the MonoBehaviour class
script reference page. The following are some common and important
events
18
Event Functions
Regular Update Events
A game is rather like an animation where the animation frames are
generated on the fly. A key concept in games programming is that of
making changes to position, state and behavior of objects in the game just
before each frame is rendered
The Update function is the main place for this kind of code in Unity.
Update is called before the frame is rendered and also before animations
are calculated
19
Event Functions
Regular Update Events
The physics engine also updates in discrete time steps in a similar way to
the frame rendering
A separate event function called FixedUpdate is called just before each
physics update. Since the physics updates and frame updates do not
occur with the same frequency, you will get more accurate results from
physics code if you place it in the FixedUpdate function rather than
Update
20
Event Functions
Regular Update Events
LateUpdate is handy for making additional changes after Update and
FixedUpdate functions, such as adjusting a camera's orientation after a
target object has moved or overriding animation effects in script code, like
making a character's head look towards a target object
21
Event Functions
Initialization Events
Initialization code before gameplay updates is crucial
Start is called before the first frame or physics update, while Awake is
called for each scene object at scene load
Although Start and Awake order is arbitrary, all Awake functions finish
before the first Start, allowing Start code to utilize prior initializations in
the Awake phase
22
Event Functions
GUI events
Unity has a system for rendering GUI controls over the main action in the scene
and responding to clicks on these controls. This code is handled somewhat
differently from the normal frame update and so it should be placed in the OnGUI
function, which will be called periodically
Detect mouse events over a GameObject for actions like targeting or displaying
character information. OnMouseXXX event functions (e.g., OnMouseOver,
OnMouseDown) enable scripts to react to mouse actions. For instance, if the
mouse button is pressed over an object, the object's script's OnMouseDown
function is called if it exists
23
Event Functions
Physics events
The physics engine triggers event functions in an object's script for
collisions
OnCollisionEnter, OnCollisionStay, and OnCollisionExit signal contact
events, while OnTriggerEnter, OnTriggerStay, and OnTriggerExit are
for Trigger colliders. These functions provide collision details when
multiple contacts occur during a physics update, passing parameters like
collision position and incoming object identity
24
Script Serialization
Serialization is the automatic process of transforming data structures or
object states into a format that Unity can store and reconstruct later
Some of Unity’s built-in features use serialization; features such as saving
and loading, the Inspector window, instantiation, and Prefabs
How you organise data in your Unity project affects how Unity serializes
that data and can have a significant impact on the performance of your
project. The next slides are some guidance on serialization in Unity and
how to optimize your project for it
25
Script Serialization
Hot reloading
Hot reloading is the process of creating or editing scripts while the Editor is open and
applying the script behaviors immediately. You do not have to restart the game or Editor
for changes to take effect
When you change and save a script, Unity hot reloads all the currently loaded script data.
It first stores all serializable variables in all loaded scripts and after loading the scripts, it
restores them. All data that is not serializable is lost after a hot reload
Saving and loading
Unity uses serialization to load and save Scenes, Assets, and AssetBundles to and from
your computer’s hard drive. This includes data saved in your own scripting API objects
such as MonoBehaviour components and ScriptableObjects.
Many of the features in the Unity Editor build on top of the core serialization system. Two
things to be particularly aware of with serialization are the Inspector window, and hot
reloading.
26
Script Serialization
The Inspector window
When you view or change the value of a GameObject’s component field in the
Inspector window, Unity serializes this data and then displays it in the Inspector
window. The Inspector window does not communicate with the Unity Scripting
API when it displays the values of a field.
If you use properties in your script, any of the property getters and setters are
never called when you view or change values in the Inspector windows as Unity
serializes the Inspector window fields directly. This means that: While the values
of a field in the Inspector window represent script properties, changes to values
in the Inspector window do not call any property getters and setters in your script
27
Script Serialization
Serialization rules
Serializers in Unity run in a real-time game environment. This has a significant
impact on performance. As such, serialization in Unity behaves differently to
serialization in other programming environments. Outlined below are a number
of tips on how to use serialization in Unity
How to ensure a field in a script is serialized
Ensure it:
1. Is public, or has a SerializeField attribute
2. Is not static
3. Is not const
4. Is not readonly
28
Script Serialization
Has a fieldtype that can be serialized:
• Primitive data types (int, float, double, bool, string, etc.)
• Enum types (32 bits or smaller)
• Fixed-size buffers
• Unity built-in types, for example, Vector2, Vector3, Rect, Matrix4x4, Color,
AnimationCurve
• Custom structs with the Serializable attribute
• References to objects that derive from UnityEngine.Object
• Custom classes with the Serializable attribute (See Serialization of custom
classes).
• An array of a field type mentioned above
• A List<T> of a field type mentioned above
29
Script Serialization
Note: Unity doesn’t support serialization of multilevel types (multidimensional
arrays, jagged arrays, dictionaries, and nested container types). If you want to
serialize these, you have two options:
• Wrap the nested type in a class or struct
• Use serialization callbacks, by implementing ISerializationCallbackReceiver, to
perform custom serialization
30
Script Serialization
Serialization of custom classes
For Unity to serialize a custom class, you must ensure the class:
Has the Serializable attribute
isn’t static
When you assign an instance of a UnityEngine.Object-derived class to a field and
Unity saves that field, Unity serializes the field as a reference to that instance. Unity
serializes the instance itself independently, so it isn’t duplicated when multiple fields
are assigned to the instance. But for custom classes which don’t derive from
UnityEngine.Object, Unity includes the state of the instance directly in the
serialized data of the MonoBehaviour or ScriptableObject that references them.
31
Script Serialization
Serialization of custom classes
There are two ways that this can happen:
• Inline serialization: By default, Unity serializes custom classes inline by value
when you don’t specify [SerializeReference] on the field that references the
class. This means that if you store a reference to an instance of a custom class in
several different fields, they become separate objects when serialized. Then,
when Unity deserializes the fields, they contain different distinct objects with
identical data.
• [SerializeReference] serialization: If you do specify [SerializeReference], Unity
establishes the object as a managed reference. The host object still stores the
objects directly in its serialized data, but in a dedicated registry section.
32
Script Serialization
Serialization of custom classes
[SerializeReference] adds some overhead but supports the following cases:
• Handling null fields: [SerializeReference] supports fields that can be null, unlike inline
serialization which replaces null with an inline object with unassigned fields.
• Managing multiple references: Without [SerializeReference], storing a reference to an object in
different fields results in separate objects when serialized.
• Dealing with graphs and cyclical data: [SerializeReference] is essential for handling cycles in
data, preventing unexpected issues like strange Inspector behavior, console errors, or infinite
loops.
• Ensuring polymorphism: When using [SerializeReference], Unity correctly serializes fields of
both the parent and derived classes, preventing issues during deserialization.
• Providing stable identifiers: [SerializeReference] is useful when a data structure requires a stable
identifier to point to a specific object without hardcoding its array position or searching the entire
array. Check Serialization.ManagedReferenceUtility.SetManagedReferenceIdForObject for
more details.
33
Script Serialization
Serialization best practice
• Optimize Unity's serialization by aiming for the smallest data sets. This isn't about
saving disk space but ensuring backward compatibility.
• Avoid serializing duplicate or cached data to prevent errors in backward
compatibility.
• Also, steer clear of nested, recursive structures referencing other classes.
Serialized structures should have a consistent layout, only dependent on script
exposure, and use classes derived from UnityEngine.Object to reference other
classes without embedding contents.
34