VG1, Quest 2 - Physics Maze

Download Files

Supporting files for VG1 quests are part of a single archive that you can download here.

Create Scene

Within the same Unity Project as Quest 1, open the File > New Scene menu. Select the Lit 2D (URP) scene template.

Unity will open a new scene as an unsaved file called Untitled. Save the scene as a Q2 scene file in the Scenes folder using the File > Save menu.

Checking the Hierarchy should confirm the file has saved and that you will be doing the rest of these steps in the Q2 scene.

Setup Folders and Import Files

Import the supplied Q2 graphics into the /Assets/Textures/Q2/ folder.

Ship Sprite Settings

Select the ship0 sprite in the Project tab to configure it in the Inspector tab. Change the PPU to 48 so that the graphic is properly sized. The Point filter mode is used when the artist intent of the graphics is to render pixel art. Pixel art is known for stylistically emphasizing the crispness of pixels which would otherwise be smoothed out in the default settings. Configuring graphics incorrectly can make them appear distorted or blurry. Even if you don't identify as an artist, you are responsible for not breaking the art. Save your changes by clicking the Apply button.

Environment Sprite Settings

Use similar settings for the space environment graphics. In older versions of Unity, you may have to select the Multiple Sprite Mode setting manually. We will discuss the significance of the Multiple option in the next step.

Multi-Slice Sprites

When a graphics file is imported with Multiple selected as the Sprite Mode, the engine can be configured to interpret multiple individual graphics from a single file. It is typical for related sprites to be organized together in a single file known as a Sprite Atlas or a Spritesheet.

Clicking the arrow button next to a texture asset will reveal all of the individual sprites.

Unity performs this process automatically, but there are often situations when you will want to refine the slicing of a spritesheet. You may also encounter older versions of Unity which require you to perform your own slicing.

Click the "Open Sprite Editor" button in the Inspector to open the Sprite Editor tool. You will see that Unity has already sliced individual graphics it has detected within the spritesheet. Something we want to refine in this step is the excess spacing around each of the sprites, which will cause problems with our physics collisions in an upcoming step.

Click the Slice menu, set Type to Automatic, and click the Slice button. You will notice that the slicing of the sprites is tighter around all of the graphics. Click the Apply button to finalize these changes.

If you click an individual graphic, you can see how it is configured as its own sprite.

The automatic slice depends on transparency separating individual sprites in the parent sheet. There are alternate options for slicing based on a grid when transparency alone does not produce the intended sprites.

Set Aspect Ratio to 16:9

The Game tab previews how the game looks to players. In a commercial game, you would ensure your game renders properly across a variety of screen shapes and resolutions. For classroom purposes, we will start with a 16:9 aspect ratio for most of our assignments, so that we can be fair and consistent when grading projects across different devices. (Commercially, this is an unrealistic assumption because we can't guarantee what kind of monitor the player has.) If you don't format your games for 16:9, it is possible we will not see a functional game when we grade your assignments.

Create Player GameObject and Components

The order components are added is important. The Collider knows what shape to take based on the sprite that is assigned in the Sprite Renderer. If there is no Sprite Renderer present when a Collider is added, the Collider may not choose the right shape that matches your graphics.

A Rigidbody component influences our gameobject as part of a physics simulation. The physics settings in these assignments should always be configured precisely as pictured.

A Collider gives our gameobject physical boundaries. When none of the geometric primitive shapes (circle, capsule, square) are a good match, we use a Polygon Collider to "fit" more complex shapes to a reasonable amount of precision.

Rigidbody and Collider are separate components because it is also possible for an object to have a rigidbody with no collider, and for a collider object to have no rigidbody. (Imagine a game of two ghost characters throwing a ghostly baseball that can pass through walls, while it still follows a simulated trajectory.)

If your Polygon Collider did not "fit" to the shape of the spaceship, click the triple dots to the right of the component and click Reset.

Create Player Script

Create RotatingShipController.cs in /Assets/Scripts/Q2/

RotatingShipController.cs

using UnityEngine;
using UnityEngine.InputSystem;

namespace Q2 {
	public class RotatingShipController : MonoBehaviour
	{
		// Outlets
		Rigidbody2D _rb;

		// Configuration
		public float speed;
		public float rotationSpeed;

		// Methods
		void Start() {
			_rb = GetComponent<Rigidbody2D>();
		}

		void Update() {
			// Turn Left
			if(Keyboard.current.leftArrowKey.isPressed) {
				_rb.AddTorque(rotationSpeed * Time.deltaTime);
			}
			
			// Turn Right
			if(Keyboard.current.rightArrowKey.isPressed) {
				_rb.AddTorque(-rotationSpeed * Time.deltaTime);
			}
			
			// Thrust Forward
			if(Keyboard.current.spaceKey.isPressed) {
				_rb.AddRelativeForce(speed * Time.deltaTime * Vector2.right);
			}
		}
	}
}

Attach and Configure Player Script

PlayTesting "Game Feel"

While the game is running, try different Linear Drag and Angular Drag values on the Player's Rigidbody2D as well as different Speed and Rotation Speed values on the RotatingShipController. Notice how changing these values drastically affects the "Game Feel".

The values supplied in these instructions represent a deliberate attempt to create an appropriate experience for the player. Although these game design choices are ultimately subjective, we ask that you use the numbers in the instructions so that we can grade everyone fairly and consistently.

When you stop playing the game, these settings will reset to their pre-execution values. The game you submit must use the numbers prescribed in the instructions.

Create Obstacle GameObject

Create an Obstacle GameObject. Set the Sprite before adding the PolygonCollider, so the engine knows what shape to generate.

All of your obstacles should have colliders that match their visuals.

Create Maze Obstacle Script

Create MazeObstacle.cs in /Assets/Scripts/Q2/ and attach it to the Obstacle object.

Our Obstacle objects will check for Collision events with the Player and reload the Scene.

MazeObstacle.cs

using UnityEngine;
using UnityEngine.SceneManagement;

namespace Q2 {
	public class MazeObstacle : MonoBehaviour
	{
		void OnCollisionEnter2D(Collision2D collision) {
			// Reload scene only when colliding with player
			if(collision.gameObject.GetComponent<RotatingShipController>()) {
				string currentScene = SceneManager.GetActiveScene().name;
				SceneManager.LoadScene(currentScene);
			}
		}
	}
}

Scene Setup

The SceneManager can only load scenes included in the Build Profile's Scene List. Open File > Build Profiles and navigate to Scene List.

Ensure the current Scene is listed in Scene List and is checked. You can drag scenes in from the Projects tab.

Level Design

Create a challenging Level Design in which the Player must navigate through Obstacles to reach a Goal.

You do not need to script the Goal for this assignment. A Goal graphic is all that is necessary.

You are required to use all six asteroid variations. You must ensure all the asteroids have a collider shape that matches their graphics. Make use of the full 16:9 screen space when placing obstacles throughout the entire screen and in between the spaceship and goal, so that the player must overcome an intentional challenge using all of the controls. The challenge should actually be beatable.

Playtest

Playtest your level design and adjust the level layout until you are satisfied with the game feel.

Create Level Boundaries

Ensure your Game tab is set to an Aspect Ratio of 16:9.

Obstacles do not always have graphics. In this step, we will create an example of a physical obstacle that has no visuals.

Create Obstacles that represent the level boundaries by making a GameObject that has 2D BoxColliders but no SpriteRenderer. Practice using the "Edit Collider" button to shape the Collider. DO NOT use the Transform Scale to stretch it.

The boundary should line up right at the outside edge of the 16:9 camera line. It would be frustrating for the player if the game were to reset when the player touches some other arbitrary position within the screen.

Finalize all four level boundaries. Ensure there are no gaps where the ship could fly out of the level. Align all of the boundaries right at the 16:9 screen edges without going into the viewable screen space.

Play your game again with the added difficulty and adjust your level design balance for game feel.

Save and Test

Playtest to ensure all interactions work as expected and that the addition of any new features hasn’t broken any earlier interactions.

Submit Assignment

SAVE any open files or scenes.

Submit your assignment for grading following the instructions supplied for your particular classroom.