Fun with the Tools and Beginning Scripting
Your first Unity program: four sprites that fly apart, grow, and come back together on the arrow keys. Due date: see the course website.
Objective
Get familiar with Unity, the tool we'll use for the rest of the quarter, and start controlling objects from a script. Also use this exercise to:
- Gauge your comfort with the kind of learning this class expects, mainly how to use Unity as a tool.
- Practice self-learning: you get basic directions and an example, and you figure out the details and variations yourself.
- Learn the submission process, so you know exactly what's involved in turning in a programming assignment.
Coverage
Unity-specific skills you'll need, practice, and demonstrate:
▶Basics
- Open and work with the Unity editor
- Set up a 2D camera, including the world size
- Build to a PC EXE
◆Unity objects
- Textures and 2D sprite objects
- Attach scripts (MonoBehaviours) to GameObjects
- Use the Transform to change position and size
⌨User interaction
- Polling keyboard state with the Input System
- Frame-rate-independent movement with
Time.smoothDeltaTime
📦Saving a project
- You only need three folders: Assets, Packages, ProjectSettings
- UserSettings, Library, Temp, Logs, obj and .vs are not needed or are regenerated by Unity; don't submit them
GreenArrowBehavior.cs before you begin.
What to build
Take a look at my solution first. Building takes time: a WebGL build can take 10 to 20 minutes, and an EXE a few minutes. Always reserve time to build before the deadline. You only need to build and submit the PC EXE.
Camera
- Main Camera: Projection Orthographic, Size 50.
- The world therefore spans y = −50 to +50 (a total height of 100). The width depends on the Game window's aspect ratio.
Initial scene
Four sprite objects, each created from an image and each of size 1 (Transform Scale (1, 1, 1)), at:
| Object | Start position | Moves within |
|---|---|---|
| Upper-right | (1, 1) | (1, 1) to (50, 50) |
| Upper-left | (-1, 1) | (-1, 1) to (-50, 50) |
| Lower-right | (1, -1) | (1, -1) to (50, -50) |
| Lower-left | (-1, -1) | (-1, -1) to (-50, -50) |
Any image works, for example Egg.png (the one in my solution) or GreenUp.PNG from the Module 1 self-exercise. Give each object a different color through its SpriteRenderer's Color (a tint), so each one is easy to tell apart.
Interaction
| Key | Position | Size |
|---|---|---|
| ↑ held | All four move away from the origin along their 45° diagonal at 10 units/second | All four grow at 0.75 per second |
| ↓ held | All four move toward the origin along their diagonal at 10 units/second | All four shrink at 0.75 per second |
| Limits | Each object's |x| and |y| stay within [1, 50] | Scale stays within [1, 6] |
| Q | Quits the application | |
Application.Quit() does nothing in the editor or in a WebGL build. It only works in the built EXE, so test Q there. Your code isn't broken if Play mode keeps running.
Speed and time: Time.smoothDeltaTime
Update() runs once per frame, and different computers run at different frame rates: 60, 144 or more frames per second. If you move an object by a fixed amount every frame, it moves more than twice as fast on a 144 Hz machine as on a 60 Hz one. To make speed mean the same thing everywhere, express it in units per second, and multiply by the time the last frame took. Unity provides that as Time.deltaTime, and Time.smoothDeltaTime is a smoothed (averaged) version that avoids jitter when one frame happens to take longer than the others. So each frame, an object moving at 10 units/second moves 10 * Time.smoothDeltaTime units, and a scale changing at 0.75 per second changes by 0.75f * Time.smoothDeltaTime. After one second of frames, those add up to about 10 units and 0.75, whatever the frame rate.
float dt = Time.smoothDeltaTime; // seconds the last frame took (smoothed)
float distance = kMoveSpeed * dt; // kMoveSpeed = 10f units per second
float growth = kScaleRate * dt; // kScaleRate = 0.75f per second
We'll use this idea in every example from Module 2 on.
Reading the keyboard
Use the Input System, exactly as in Module 1's GreenArrowBehavior.cs:
using UnityEngine;
using UnityEngine.InputSystem;
// ... inside your MonoBehaviour:
void Update()
{
float direction = 0f; // +1 away from origin, -1 toward it
if (Keyboard.current.upArrowKey.isPressed)
direction += 1f;
if (Keyboard.current.downArrowKey.isPressed)
direction -= 1f;
if (Keyboard.current.qKey.wasPressedThisFrame)
Application.Quit();
// Your code: move and scale the four objects using
// direction and Time.smoothDeltaTime, then clamp.
}
Input.GetAxis()
New Unity 6 projects use only the new Input System, so the old Input.GetAxis("Vertical") throws an InvalidOperationException as soon as the game runs. Use Keyboard.current as shown above.
- Each object's diagonal direction is just its starting position, normalized:
transform.localPosition.normalized. Mathf.Clamp(value, min, max)keeps a number within a range.- Scale lives in
transform.localScale(aVector3). - One script on each object, or one script that references all four: both are fine.
Stretch goal (optional, not graded)
Finished early? Try one of these:
- Space resets all four objects to their starting positions and size 1.
- ←/→ rotate all four objects, at a rate given in degrees per second.
Submission
Your submission has two parts:
- A zip file named
YourNameEX1.zipcontaining your entire project: every file in Assets, Packages and ProjectSettings, and nothing more. - A separate folder with your PC EXE build. We'll double-click the EXE to run your project.
Update() moves, scales and clamps the objects.
Self-check before you submit
- I unzipped my zip into a new, empty folder and opened it in Unity 6000.3.11f1. It opens and runs.
- The zip has only Assets, Packages and ProjectSettings. No UserSettings, Library, Temp, Logs, obj or .vs.
- Double-clicking the EXE in my build folder runs the game.
- Q quits the EXE.
- My four objects are sprites made from an image, not built-in shapes.
- Holding ↑ stops at the corners (±50) and at size 6; holding ↓ stops at (±1, ±1) and size 1.
- My script has the 2–3 sentence explanation comment at the top.
Credit distribution
| Item | Sub-item | Category |
|---|---|---|
| Camera setting: Orthographic, Size 50 | 10% | |
| Scene setup: four image sprites at (±1, ±1), size 1, different colors | 10% | |
| Up/Down arrows: position | 30% | |
| ↑ moves objects away from the origin along the diagonal at 10 units/second | 10% | |
| ↓ moves objects toward the origin along the diagonal at 10 units/second | 10% | |
| Positions stay within ±1 and ±50 | 10% | |
| Up/Down arrows: scale | 30% | |
| ↑ scales objects up at 0.75/second | 10% | |
| ↓ scales objects down at 0.75/second | 10% | |
| Scale stays between 1 and 6 | 10% | |
| Q quits the application (in the EXE) | 10% | |
| Proper submission | 10% | |
| Zip unzips and runs in the editor, with only the four project folders | 5% | |
| Separate EXE folder; double-click runs the game | 5% | |
| Total | 100% |