Final exercise: ship the game
everything from tab 01–05 · signed release build on a real phone
The final exercise of the course: put the Arena — waves, enemies, touch controls and all — on a real phone as a signed release build that holds its frame rate for five minutes (60 FPS where the phone can, never below 30) and remembers your progress when you kill the app.
what you reuse
Not a screenshot in the editor — an app icon on a phone that someone else could install.
Part 1 — clean up the scene
Open Arena.unity — the scene you have been growing since tab 01 — and check the GameDirector still has its spawn points.
Delete anything left over from testing: spare cameras, stray lights, blocks you moved aside.
There must be exactly one AudioListener, one EventSystem and one CinemachineBrain in the scene.
Check the touch canvas from tab 03 is still there and switches itself on when the game runs on a phone.
Part 2 — configure the build
Project Settings → Player
Company Name your studio // not DefaultCompany
Product Name Arena
Package Name com.yourstudio.miniarena // permanent
Version / Bundle Code 1.0.0 / 1
Default Orientation Landscape Left
Scripting Backend IL2CPP
Target Architectures ARMv7 + ARM64 // ARM64 is mandatory
Minimum API Level 24
Managed Stripping Medium
Graphics APIs Vulkan, OpenGLES3 // remove OpenGLES2
URP Asset (mobile)
Shadow Max Distance 40
Cascade Count 1
HDR off
MSAA disabled
Render Scale 0.85
Assets/link.xml
preserve SaveData // or stripping deletes itvoid Awake()
{
Application.targetFrameRate = 60;
QualitySettings.vSyncCount = 0;
Screen.sleepTimeout = SleepTimeout.NeverSleep;
DontDestroyOnLoad(gameObject);
}Part 3 — the first build is always broken
Expect it. Build a Development Build first, install it, and read adb logcat while you play. The bugs that only exist on device are the whole point of this exercise.
adb devices # is the phone actually connected?
adb logcat -c && adb logcat -s Unity # clear, then watch only Unity
# after the build
adb install -r Builds/arena-dev.apk
adb shell monkey -p com.yourstudio.miniarena 1The five bugs almost everyone hits
Pink materials — a shader did not convert to URP. Convert the materials, rebuild.
Buttons do nothing — no EventSystem, or an invisible full-screen Image is eating the raycasts.
Save file empty — IL2CPP stripping removed SaveData. Add it to link.xml.
20 FPS on device, 200 in the editor — realtime shadows and post-processing. Check the URP asset.
UI cut off by the notch — the safe area fitter is missing on the touch canvas.
Part 4 — the release build
Create a keystore, save it OUTSIDE the project, back it up twice. Losing it can lock you out of updating the app.
Add *.keystore to .gitignore before you commit anything.
Untick Development Build, tick Build App Bundle, and build the .aab.
Also keep a signed .apk — that is the one you hand to a friend to test.
Done when
- ✓The app is installed on a physical phone, launched from its own icon, not from Unity.
- ✓You can complete a full loop with touch alone: move, aim the camera, cast all three skills, kill an enemy.
- ✓Every UI element is inside the safe area on a phone with a notch, and anchored so a tablet does not break it.
- ✓Backgrounding the app and force-closing it, then reopening, restores your health, position and gold.
- ✓Five minutes of continuous play stays at or above 30 FPS — measured at minute five, not minute one.
- ✓adb logcat -s Unity shows no exceptions during a full play session.
- ✓A signed .aab exists, built with Development Build unticked.
- ✓Someone else installed your .apk on their phone and it ran.
Numbers to hit
| Metric | Target | Why |
|---|---|---|
| FPS at minute 5 | ≥ 30 | Thermal throttling makes minute 5 the only honest measurement. |
| Build size (.aab) | ≤ 150 MB | Above 150 MB Google Play needs extra delivery configuration. |
| Cold start to playable | ≤ 5 s | Players close apps that show a black screen for longer. |
| Memory in use | ≤ 600 MB | Above that a 3 GB phone starts killing your app in the background. |
| Exceptions in logcat | 0 | One NullReference per frame is a silent frame-rate killer. |
If you want more
Upload the .aab to Play Console as an internal test and install it from the Play Store on your own phone.
Add a device-tier check that drops render scale and shadow distance on phones with under 3 GB RAM.
Build the same project for iOS and compare the frame rate on similar hardware.
Add an in-game FPS + memory overlay you can toggle, so testers can report real numbers.
That is the whole course
You started at 'what is a variable' and finished with a signed build on a phone. That is the entire pipeline.
Everything after this is depth, not breadth: better animation, smarter enemies, real level design, a real art style.
The next thing to build is a game with one mechanic and five minutes of content that you actually finish. Finishing is the rarest skill in this field.