Reviewed: 29 August 2026 · Next review: 28 February 2027
Author: Ozlin Info Editorial Team · Human review: Lin
A useful first game is small enough to finish and structured enough to test. This guide builds one scene in which a player moves a square to a goal, shows a success message and can be built for a selected target. It uses a pinned Unity 6 editor, the current Input System and Rigidbody2D.linearVelocity rather than the legacy Input.GetAxis workflow.
The example is educational. Run it in a new project or branch, record exact versions and inspect every imported asset and package before using it in production.
1. Pin the project and define “done”
Install a supported Unity 6 LTS editor through Unity Hub with the module for the first target platform. Record the full editor version. Create a 2D project and initialise source control before adding assets.
Commit Assets, Packages and ProjectSettings. Exclude generated Library, Temp, Logs, obj and local build directories using an appropriate Unity ignore file. Do not commit signing keys, service credentials or generated store packages.
Write a tiny acceptance test:
- the game opens directly into one scene;
- WASD, arrow keys or a gamepad stick moves the player;
- the player cannot pass through the border;
- reaching the goal displays a success panel;
- Escape or a visible control can exit or return according to platform; and
- a built player runs on the selected target device.
This boundary prevents a first project from expanding into inventory, networking and procedural worlds before its basic loop works.
2. Build the scene with licensed placeholders
Create and save Assets/Scenes/Main.unity. Add a camera with an orthographic projection. Use simple coloured sprites created in the editor or original files for the player, border and goal. Record the source and licence of anything downloaded; “free” does not define reuse or redistribution rights.
Create sorting layers for background, world and interface if needed. Use consistent world units. Add four static border objects with BoxCollider2D, and give the player:
SpriteRenderer;Rigidbody2Dwith gravity scale set to zero for this top-down example; andBoxCollider2Dor another shape matching the visual body.
Do not resize a collider accidentally through a deeply scaled parent. Turn on collision gizmos and check the actual shape. Place the goal with a BoxCollider2D marked as a trigger.
3. Create action-based input
Unity documents the Input System as the extensible alternative recommended for new projects, while the old UnityEngine.Input API is legacy (Unity — Input System, Unity — legacy Input API).
Install or confirm the released Input System package compatible with the pinned editor. Create Assets/Input/GameInput.inputactions with an action map named Player and a Move action:
- action type:
Value; - control type:
Vector2; - a 2D Vector composite for WASD;
- a second 2D Vector composite for arrow keys; and
- a gamepad left-stick binding.
Save the asset. The package can bind multiple devices to one action and supports later rebinding through overrides (Unity — Input bindings). Input handling belongs to gameplay actions rather than keyboard-specific code.
4. Move the player through Rigidbody2D
Create Assets/Scripts/TopDownMover.cs:
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(Rigidbody2D))]
public sealed class TopDownMover : MonoBehaviour
{
[SerializeField] private InputActionReference moveAction;
[SerializeField, Min(0f)] private float speed = 5f;
private Rigidbody2D body;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void OnEnable()
{
moveAction.action.Enable();
}
private void OnDisable()
{
moveAction.action.Disable();
if (body != null)
{
body.linearVelocity = Vector2.zero;
}
}
private void FixedUpdate()
{
Vector2 input = moveAction.action.ReadValue<Vector2>();
if (input.sqrMagnitude > 1f)
{
input.Normalize();
}
body.linearVelocity = input * speed;
}
}
Attach it to the player and assign the Move action reference. Unity 6's current Rigidbody2D API exposes linearVelocity as the linear velocity vector (Unity — Rigidbody2D.linearVelocity). Pinning the editor matters because older tutorials and versions use different API names.
The script reads intent and applies velocity during the physics step. Normalising values above magnitude one prevents diagonal keyboard input from exceeding the configured speed. A platformer would need gravity, grounded checks, jump rules and a different controller; do not reuse this top-down movement unchanged.
5. Add one goal and explicit game state
Create a GoalZone component that raises one success event the first time the player enters. Keep outcome logic outside the movement script. A small GameFlow component can own Playing and Completed states, disable player input on completion and open a success panel.
Validate the collider belongs to the player using a component or layer, not an object name. Guard repeated trigger callbacks so the score or success transition is idempotent. If the scene reloads, the new flow owner should start from a deliberate state.
Add a reset control through an input action or accessible interface button. Do not require a mouse if gamepad is supported. Avoid relying only on colour or sound to communicate success.
6. Add readable interface, audio and tests
Create a Canvas with brief controls and a hidden success panel. Anchor elements so they survive several aspect ratios and safe areas. Use readable contrast and a logical navigation order. If a sound confirms success, keep the visible message as an alternative.
Test the acceptance list in Play Mode, then add automated checks where useful:
- an Edit Mode test for movement-vector normalisation;
- a Play Mode test that the border blocks the body;
- a Play Mode test that entering the goal completes once; and
- a content check that the build scene is present.
Try keyboard and a physical gamepad, unplug the gamepad, resize the window, lose and regain focus, and reload the scene. Watch the Console for exceptions and warnings. A tutorial that “looks right” but emits an error every frame is not complete.
7. Create a Build Profile and run the player
Open File → Build Profiles. Unity 6 Build Profiles let a project store multiple configurations and their scene lists as assets (Unity — Build Profiles). Create a development profile for the first target, add Main.unity, select the correct platform module and build to a clean local output directory.
Run the built player and repeat the acceptance test. The editor does not reproduce every resolution, file path, input, graphics or lifecycle behaviour. For mobile, install on a physical device and check touch design, safe areas, suspend/resume, performance and package identity. Store submission additionally requires current signing, SDK, privacy and listing work; a local build is not store approval.
Record the build date, source revision, editor and package versions and test device. Make a source-control tag when the seven-step sample passes. You now have a finished, reproducible base that can accept one new feature at a time.
For a scoped software build or review, see Ozlin Info's secure web and software delivery service; related first-party game-engineering context is in the Projects archive, or contact Ozlin Info.
Related reading: Cross-platform Unity architecture and delivery.
General-information disclaimer
This article provides an educational example, not a supported Unity package, storefront approval or production controller. Verify the pinned editor, packages, licences, platform requirements and tests for the actual project.
AI-assistance disclosure
AI tools assisted with source discovery, example drafting and copyediting. A human reviewer must create the project, compile the script, run the tests and verify current Unity and target-platform behaviour before publication or use.
Primary sources checked
- Unity — 2D game creation workflow
- Unity — Input System
- Unity — Input bindings
- Unity — legacy Input API
- Unity — Rigidbody2D.linearVelocity
- Unity — Build Profiles
Source access date: 29 August 2026.
