1 of 32

Game Programming Crash Course �Part 2: The Second Part

2 of 32

Howdy!

I’m Ben Vinson

3 of 32

My most well known work...

4 of 32

1.

Core Concepts

Functions, GameObjects and data types - oh my!

5 of 32

What are functions?

  • Blocks of code that may perform logic on input and generate output
  • Allow you to easily re-use code
  • Help simplify complex logic by breaking it down into smaller steps
  • Enable you to test smaller parts of your program in isolation
  • Most programming languages have a “standard library” of useful functions

6 of 32

A basic function to add 2 numbers

int Add(int a, int b) {

return a + b;

}

Return type

Function name

Argument list

Function body

7 of 32

What is a GameObject?

  • Specific to Unity, but many game engines have similar concepts
  • Has position/rotation/scale (a transform)
  • Can contain multiple components and behaviors (scripts)
  • Part of a hierarchy
    • Can have a parent, children, and siblings
  • You will be interacting with them a lot

8 of 32

Cube GameObject

Components

9 of 32

What is C#? What are data types? �Why no UnityScript? 😭

  • C# is a strongly-typed object-oriented programming language
    • Strongly-typed means variables have both a name and a type: integer, string, boolean, etc.
    • Strict typing rules help prevent human error
    • More verbose and complex
  • C# is generally more fully featured and more efficient than UnityScript/JS
  • Typically easier to find example C# code

10 of 32

2.

Learning via Experimentation

“Observation is a passive science,

experimentation an active science.”

-Claude Bernard

11 of 32

  • Allow for any number of cubes
  • Add a countdown timer to allow “losing”
  • Spawn cubes at random intervals
  • More levels with increasing difficulty
  • Tighten up the graphics and add TONS OF PARTICLES

12 of 32

13 of 32

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!";

}

}

14 of 32

15 of 32

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

...

}

16 of 32

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();

}

17 of 32

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 :(";

}

}

}

18 of 32

19 of 32

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

20 of 32

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

21 of 32

22 of 32

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

}

23 of 32

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);

}

}

}

24 of 32

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;

...

}

25 of 32

26 of 32

Time to cheat (just a little bit) 👍

  • Import the Unity Post Processing Stack
  • Totally free and open source
  • Gobble up some free particle effects from the asset store while we’re there
  • Profit!

27 of 32

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);

...

}

}

28 of 32

The final product

Including temporal FSAA, grain filter, motion blur, chromatic aberration, and so many particles!

29 of 32

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

30 of 32

What now?

  • As Brad said, never a better time to learn
  • Check out Udemy, edX, Lynda, etc
    • Seriously, you can take an MIT CS course FOR FREE
    • HIGHLY recommend the Udemy Unity Course
    • Pick some courses and stick with them
  • You will be frustrated
    • This stuff is not easy, tenacity is important
  • It will be worth it
    • Making games is a great hobby/artistic outlet
    • Personal projects are great for resume building

31 of 32

Once you gain some experience, you will never play games the same way again...

32 of 32

�Thanks! Code is available at:https://github.com/BenV/roll-a-ball-experiment

Any Questions?�