Intro to Game Engine, Unity, and C#
What is a Game Engine?
Let's break this question down. First of all...
What is a Game?
For example, in a game of tag, what are the rules for...
- THE SETUP -- how do you decide who's "it"? when can they start tagging people?
- THE LEVEL / PLAYING FIELD -- how far can players go before they're "out-of-bounds"? are there safe zones where people can't be tagged?
- PLAYER BEHAVIOUR -- are players only allowed to travel in a certain manner (e.g. speedwalking, but no running), and how can that be enforced (e.g. speedwalking means both feet cannot be lifted off the ground at the same time at any moment.) If someone gets tagged, what happens to them? Do they freeze in position, become "it", or are they out of the game?
- CONCLUDING THE EXPERIENCE -- how do you know when the game has ended, and who the winner/loser is (if any)?
"Is xxx a game?"
Technically, this question is irrelevant to this class.
Regardless of what you end up making for your assignments, you'll eventually have to make decisions about the parameters and conditions of your project (which you could think of as being "the rules of your game") and consider how one's interaction / encounter of these "rules" will affect their overall experience of it.
In this class, we will focus on how to implement these rules using game engines, so that you can explore its creative affordances for designing particular experiences.
What is an Engine?
Consider the following definitions from the Wikitionary page for "Engine":
"A complex mechanical device which converts energy into useful motion or physical effects."
In a mechanical sense, an engine is an energy converter that can transform certain type(s) of input into other type(s) of "productive" output.
"A person or group of people which influence a larger group; a driving force."
"Anything used to effect a purpose; any device or contrivance; an agent."
In an abstract sense, an engine is an information carrier that can contain, transfer, and transform ideas, beliefs, and principles.
"A large construction used in warfare, such as a battering ram, catapult etc. [from 14th c.]"
"The part of a car or other vehicle which provides the force for motion, now especially one powered by internal combustion. [from 19th c.]"
From a historical and infrastructural standpoint, an engine is a catalyst of both the production and destruction of worlds, societies, and cultures.
"A software or hardware system responsible for a specific technical task (usually with qualifying word)."
a graphics engine; a physics engine.
In computing, an engine is a specialised machine for performing a specific task.
In this class, we will be mostly using software programs designed specifically for game development... but really, anything can be a "game engine."
It is also worth considering the various contexts in which the engine emerges, so that we can better grasp the possibilities and implications of this technology, and then decide how and where we would like to proceed with this tool.
Put them together... GAME ENGINE!
Returning to our first question:
What is a game engine?
- Tools designed specifically for developing games (e.g. Unity, Bitsy, PICO-8, in-game level builders)
- Platforms which primarily serve some other non-game-making function (if any at all), but are nonetheless used for making games. (e.g. Spreadsheets, Checkboxes, Post-war junkyards and bombsites)
If a game is "an experience that is made from the interaction between different rules", then broadly speaking, a game engine could be anything that converts rules and interaction into playable experiences.
Unity is a Game Engine
We'll spend most of this course working in the Unity game engine.
Unity, initially released in 2005, is a closed-source game engine, and Unity Technologies, the developer of the engine, has been a publicly traded company since 2020.
The engine gained popularity through being free for small, independent developers, with a relatively easy learning curve.
Compared to most other game engines, Unity also tries to avoid being aesthetically identifiable and not be tied to a particular genre of game.
Other industries use Unity for things like Architectural and Auto rendering, Film and TV production, AI training and computer vision.
Unity also contracts with the US Department of Defense for military training and simulation.
Anatomy of the Unity Editor
Read the following articles from the Unity User Manual:
Unity C#
Unity uses C#, a type of object-oriented language, as one of its primary scripting languages.
We typically write Unity C# scripts to make customised blueprints for accessing, organising, and implementing data inside our game project. This is helpful for:
- storing information such as variables and functions inside an object or class;
- programming interactive / dynamic behaviour in objects;
MonoBehaviours
Most of the time, we're working with a class called MonoBehaviour which behaves like a component that can be attached to any gameobject in our scene.
Whenever we make a new C# script in Unity, we are creating custom classes that inherit from another class called MonoBehaviour by default. This allows us to use the methods and functionality from the MonoBehaviour class.
public class NewBehaviour : Monobehaviour{...}
Let's create a Unity C# script!
When writing any sort of code, here's the general thought process:
- OUTPUT -- "I need my script to do THIS..."
- INPUT -- "... so I need to access THESE VARIABLES..."
- METHOD -- "... and call THESE FUNCTIONS in order of THIS SEQUENCE."
It is very common to start by looking for solutions on Unity's Documentation page or other community forums. There is no expectation to memorise every single thing -- the longer you work in Unity, the more familiar you become with its interface and workflow, and you'll eventually find yourself not needing to look things up as often as you used to.
Anatomy of a C# Script
If you are new to coding in C#, watch this video for a brief introduction to C# Variables and Functions in Unity.
Naming your C# Scripts
- use pascal case, (i.e. first alphabetical letter is capitalised, and every new word is marked with a capitalised case, no spaces.) e.g. MyScript.cs
- the file name of the script and the name of the MonoBehaviour must be exactly the same (case-sensitive).
- e.g. if your C# file name is "ScoreManager.cs", then the line declaring your Monobehaviour class in that script file should look like this:
public class ScoreManager : MonoBehaviour {...}
- e.g. if your C# file name is "ScoreManager.cs", then the line declaring your Monobehaviour class in that script file should look like this:
- the name must be unique -- no two MonoBehaviours should have the same name.
Namespaces
A C# script typically starts with a list of namespaces, which are reference libraries containing all the methods and classes for a specific context. The name of each namespace is typically placed after using
.
using UnityEngine
Variables and Functions
Each class has a block of code that defines what its properties (aka variables) and methods (aka functions) are. These properties and methods should be enclosed within the curly braces for that class.
public class MyNewScript : MonoBehaviour
{
public int someProperty;
void SomeMethod()
{
}
}
Variables
Variables are labelled data containers that represent properties for that class. These variables can be assigned values, and whose read/write access can be set by declaring them as public or private.
Most properties in a component are likely accessible in some way via scripting (to learn more, Unity scripting reference is your best friend!)
When creating variables:
- declare access permissions in lowercase (default:
private
) - declare what type of variable it is
float
- a numerical value that can be in decimalsint
- a numerical integer (whole numbers only)bool
- binary property that can be either assigned 'true' or 'false'string
- a sequence of characters- other public classes including
GameObject
and components (e.g.Transform
)
- name the variable
- no spaces allowed.
- use camel case.
int numberOfCamels
- use clear and descriptive nouns, the intent of this variable should be immediately apparent from its name
- if it is a bool, prefix with a verb (typically phrase as a question.)
bool isWalking, hasSpecialAbility;
- if it is a bool, prefix with a verb (typically phrase as a question.)
- use prefixes with an underscore to differentiate private member variables from public ones.
private bool _currentHealth; private static int s_winScore;
Functions
There are two main types of functions:
- method functions -- a way to group lines of code under one name; good for if you need to call a specific set of codes multiple times;
- event functions -- automatically tells Unity what to do at very particular instances in the game.
Functions may take in variables as arguments, which can be passed in parentheses () and each separated by a comma.
When creating functions:
- declare access permissions in lowercase (default:
private
) - what type of value it returns in lowercase (if any) --
void
returns no value. - name of the function in pascal case, followed by parenthesis containing any argument variables.
float MultiplyByTwo(float initialFloat){...}
Key principles of Programming in Unity C#
- Single Responsibility -- Every module of code (class, function, etc.) should have a one and only purpose in the software functionality. This will be very helpful for:
- debugging scripts
- making your scripts easily reusable for other projects.
- Keep everything private unless it absolutely needs to be public.
- if a variable just needs to be visible in the Inspector but does not need to be publicly accessible, you should keep it private then add [SerializeField] before it.
[SerializeField] bool _currentIndex;
- if a variable just needs to be visible in the Inspector but does not need to be publicly accessible, you should keep it private then add [SerializeField] before it.
- Anticipate errors, and help your script help you catch them
- if your script absolutely needs a type of component, precede your Monobehaviour declaration with
[RequireComponent(typeof(ComponentName))]
- use
Debug.Log
andDebug.LogError
to check for incorrect / null references.
- if your script absolutely needs a type of component, precede your Monobehaviour declaration with
- Use comments to contextualise your lines of code
Exercise before next class
Can you write a script that forces a GameObject to start at a specific position in the scene?