Overview
Appscape is a 2D pixel-art puzzle-platformer built with Unity for a university mobile applications course, as a three-person team project. The player runs, jumps, and pushes objects through six hand-built levels, using touch controls designed for mobile first and keyboard as a fallback for desktop play.
Each level is a self-contained physics puzzle: collect the keys needed to unlock the level’s exit, avoid instant-death hazards, and reposition moveable crates and platforms to reach otherwise out-of-reach areas.
Key features
- Touch-first controls: on-screen left/right/jump buttons wired through
Unity’s
EventTriggersystem for press-and-hold movement, alongside arrow-key input for desktop testing - Checkpoints that save full level state: not just the player’s position, but the collected/uncollected state of every key and the position, rotation, and active status of every moveable object in the level, so a death mid-puzzle doesn’t undo earlier progress
- Key-and-lock progression: each level gates its exit door behind a number of collectible keys, tracked with a live on-screen counter
- Physics-based hazards: falling weighted props that kill on impact above a velocity threshold, arrow traps that fire in timed bursts, and rolling boulders that chase the player down slopes
- Sticky platforms and teleporters: platforms the player can ride (implemented by re-parenting the player to the platform’s transform), and cooldown-gated teleport pads with a fog transition effect
- Level select and pause/options menus, with music and SFX volume
sliders persisted through
PlayerPrefs - Built entirely on free asset packs (Pixel Adventure, Cainos) for sprites and tilesets, with a custom pixel-art start/end screen and app icon
Challenges
Working as a three-person team on a single Unity project surfaced problems that don’t show up solo:
- Scene merge conflicts:
.unityscene files are large serialized YAML documents, and two people editing the same level scene in parallel produced conflicts that couldn’t be resolved with a normal text diff — the team settled on splitting work by level/scene ownership to avoid them entirely. - State that has to survive a checkpoint reload: reloading a checkpoint
naively would reset every pushable object and key to its level-start
state, undoing real progress.
GameStatesnapshots and restores object and key state explicitly rather than relying on scene reload. - Physics-based hazards feeling fair: a falling prop that kills on any
contact reads as cheap; tying the kill condition to the prop’s impact
velocity (
deadlyVelocity) meant a gentle nudge wasn’t lethal, but a genuine drop was.
What I learned
- Structuring shared state (keys, moveable objects, checkpoints) so it round-trips cleanly through save/restore, instead of leaking level-reset bugs
- Building touch-first UI input in Unity with
EventTriggerpress/hold semantics, rather than assumingInput.GetKeypolling is enough - Working inside a Unity project as a team: dividing work by scene to avoid unmergeable YAML conflicts, and agreeing on prefab ownership up front
- Tuning physics-based hazards (velocity thresholds, force impulses) until they felt readable and fair rather than arbitrary