Game Programming Crash Course �Part 2: The Second Part
Howdy!
I’m Ben Vinson
My most well known work...
1.
Core Concepts
Functions, GameObjects and data types - oh my!
What are functions?
A basic function to add 2 numbers
int Add(int a, int b) {
return a + b;
}
Return type
Function name
Argument list
Function body
What is a GameObject?
Cube GameObject
Components
What is C#? What are data types? �Why no UnityScript? 😭
2.
Learning via Experimentation
“Observation is a passive science,
experimentation an active science.”
-Claude Bernard
Modifying the Unity “Roll-a-ball” tutorial
Original function with hard-coded value
void SetCountText() {
...
// Check if our 'count' is equal to or exceeded 12
if (count >= 12) {
winText.text = "You Win!";
}
}
void SetCountText() {
...
// Check if there are any objects tagged “Pick Up” in the scene
if (GameObject.FindGameObjectsWithTag("Pick Up").Length == 0) {
winText.text = "You Win!";
}
}
Updated using GameObject.FindGameObjectsWithTag
Step 1: Set up variables and initialize them
public class PlayerController : MonoBehaviour {
...
public Text gameOverText; // Renamed from “winText”
public float timeAllowed; // Number of seconds player has to win
public GameObject timer; // UI element representing time remaining
...
// This private variable can only be modified from within this
// class, and not via the editor
private float timeRemaining;
...
}
void Start() { // Called by Unity before the first frame is rendered
...
timeRemaining = timeAllowed; // Set time remaining to time allowed
...
}
Step 2: Add game state utility functions
bool GameLost() {
// The player has lost if no more time is remaining
return timeRemaining <= 0;
}
bool GameWon() {
int cubesLeft = GameObject.FindGameObjectsWithTag("Pick Up").Length;
return !GameLost() && cubesLeft == 0; // Game not lost AND cubesLeft = 0
}
bool GameOver() {
// The game is over if the player has either won or lost
return GameWon() || GameLost();
}
Step 3: Update the time remaining each frame
void UpdateTimer() {
// Time.deltaTime is the number of seconds elapsed since the last frame.
timeRemaining = timeRemaining - Time.deltaTime;
// Scale the UI element in the X direction by the fraction of time left
float timeLeft = timeRemaining / timeAllowed;
timer.transform.localScale = new Vector3(timeLeft, 1, 1);
}
void Update() { // Update is called by Unity once per frame
if (!GameOver()) { // We don’t need to run this code if the game is over
UpdateTimer();
if (GameLost()) {
gameOverText.text = "You Lose :(";
}
}
}
void SpawnCube() {
// Clone a new cube from the original prefab
GameObject newCube = Instantiate(cubePrefab);
// Create a vector with x and z between -5 and 5
Vector3 v = new Vector3(Random.Range(-5, 5), 0.5f, Random.Range(-5, 5));
newCube.transform.position = v;
// Use Invoke to schedule another cube to be spawned in the future
Invoke("SpawnCube", Random.Range(5, 10));
}
public class PlayerController : MonoBehaviour {
...
public GameObject cubePrefab; // Set this to the cube prefab in editor
...
void Start() {
...
SpawnCube(); // Start spawning cubes at a random rate
}
Step 1: Spawn new cubes from a “prefab”
void OnTriggerEnter(Collider other) {
if (other.gameObject.CompareTag("Pick Up")) {
// If the game is not over give the player a time boost
if (!GameOver()) {
timeRemaining++; // Add one second to time remaining
}
}
}
Step 2: Add a time bonus for picking up cubes
Step 1: Add variables and a method for starting a new level
public class PlayerController : MonoBehaviour {
...
// Add some more knobs for tuning difficulty via the Unity editor
public int numLevels = 5;
// Static variables will retain their value after we re-load the scene
private static int level = 1;
...
}
void StartNextLevel() {
// Increment the level (this is shorthand for "level = level + 1")
level++;
SceneManager.LoadScene(0); // Simply reload the current scene
}
Step 2: Modify “game over” logic to account for levels
void SetScoreText() {
...
if (GameWon()) {
if (level == numLevels) {
// No more levels, let the player know that they have won
gameOverText.text = "HOLY TOLEDO, YOU BEAT THE WHOLE GAME!";
} else {
// Inform the player that they beat the current level, and
// use Invoke to start the next level in 5 seconds
gameOverText.text = "Nice work, you beat level " + level + "!";
Invoke("StartNextLevel", 5);
}
}
}
Step 3: Add a difficulty multiplier
float DifficultyMultiplier() {
// Multiplier is 0 on level 1, and increases linearly for each level
return (level - 1.0f) / (numLevels - 1.0f);
}
void SpawnCube() {
...
// Make cubes spawn faster as the difficulty increases
float modifier = (1.0f - DifficultyMultiplier() / 2.0f);
Invoke("SpawnCube", Random.Range(5.0f, 10.0f) * modifier);
}
void UpdateTimer() {
// Make the timer decrease faster as difficulty increases
float dt = Time.deltaTime * (DifficultyMultiplier() + 1);
timeRemaining = timeRemaining - dt;
...
}
void OnTriggerEnter(Collider other) {
// Reduce the time boost for pick ups as the level increases
float dt = 1.0f - (DifficultyMultiplier() * 0.75f);
timeRemaining = timeRemaining + dt;
...
}
Time to cheat (just a little bit) 👍
Add an explosion when cubes are collected
public class PlayerController : MonoBehaviour {
...
public GameObject explosionPrefab; // Hook this up in the Unity editor
...
}
void OnTriggerEnter(Collider other) {
if (other.gameObject.CompareTag("Pick Up")) {
...
// Create an explosion at the same position as the cube
Vector3 position = other.gameObject.transform.position;
Instantiate(explosionPrefab, position, Quaternion.identity);
...
}
}
The final product
Including temporal FSAA, grain filter, motion blur, chromatic aberration, and so many particles!
3.
Next Steps
“I don’t look to jump over 7-foot bars. I look around for 1-foot bars I can step over.”
-Warren Buffet
What now?
Once you gain some experience, you will never play games the same way again...
�