Exercise 1 · Individual work

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.
Most of your time should go into asking, and looking up, “how do I make Unity do …?” Let me know if that isn't true for you.
Individual workEach person must work on this exercise on their own.

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
Start from the class examples Module 1, Example 1.2 already moves a sprite with the keyboard. Read its 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.

1

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.
2

Initial scene

Four sprite objects, each created from an image and each of size 1 (Transform Scale (1, 1, 1)), at:

ObjectStart positionMoves 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)
Each object must be a sprite made from an image Import an image into your project (Texture Type: Sprite (2D and UI)) and create each object from it, e.g., drag the image into the Scene or use GameObject › 2D Object › Sprite and set its Sprite. Built-in shapes (the square, circle and other shapes under 2D Object › Sprites) and 3D objects (Cube, Quad) do not count.

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.

3

Interaction

KeyPositionSize
↑ heldAll four move away from the origin along their 45° diagonal at 10 units/secondAll four grow at 0.75 per second
↓ heldAll four move toward the origin along their diagonal at 10 units/secondAll four shrink at 0.75 per second
LimitsEach object's |x| and |y| stay within [1, 50]Scale stays within [1, 6]
QQuits the application
Why 0.75 per second? Moving from (1, 1) to (50, 50) is about 69 units along the diagonal, which takes about 7 seconds at 10 units/second. At 0.75 per second, the scale goes from 1 to 6 in about the same time, so the objects reach their largest size as they reach the corners.
About Q 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.
}
Don't use 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.
Hints
  • 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 (a Vector3).
  • 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:

  1. A zip file named YourNameEX1.zip containing your entire project: every file in Assets, Packages and ProjectSettings, and nothing more.
  2. A separate folder with your PC EXE build. We'll double-click the EXE to run your project.
Using an AI assistant? That's fine, but you must understand and be able to explain every line you submit. At the top of your main script, write a short comment (2–3 sentences, in your own words) explaining how your 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

ItemSub-itemCategory
Camera setting: Orthographic, Size 5010%
Scene setup: four image sprites at (±1, ±1), size 1, different colors10%
Up/Down arrows: position30%
↑ moves objects away from the origin along the diagonal at 10 units/second10%
↓ moves objects toward the origin along the diagonal at 10 units/second10%
Positions stay within ±1 and ±5010%
Up/Down arrows: scale30%
↑ scales objects up at 0.75/second10%
↓ scales objects down at 0.75/second10%
Scale stays between 1 and 610%
Q quits the application (in the EXE)10%
Proper submission10%
Zip unzips and runs in the editor, with only the four project folders5%
Separate EXE folder; double-click runs the game5%
Total100%
Remember to delete the other folders before zipping, especially Library. Unity regenerates it when the project opens.