A Car-Routing Parking Puzzle Game — Unity Template
Version 1.0 | Unity 6+ | URP
This asset is designed as a template and starting point for your own game development. It provides the core systems, architecture, and tools needed to build a car-routing parking puzzle game. You are expected to customize, extend, and modify this template to create your unique game. This is not a complete, ready-to-publish game — it's a foundation for developers to build upon.
Car Parking Jam is a car-routing parking puzzle game where players tap colored cars on a grid to drive them out to a row of parking slots, where matching-colored passengers automatically walk from their queues and board. Fill every car with passengers to send it off and clear the level. The game features 3D animated passengers, a built-in level editor, an automatic level generator, and a booster system.
Intuitive touch/click controls — tap any reachable car on the grid to route it to the next free parking slot. Matching colored passengers automatically walk from their queue and board.
Full Unity Editor window for designing levels with a visual grid painter — place colored cars, configure passenger queues, parking slots, locked VIP slots, and waypoint paths.
Batch-generate hundreds of playable levels with configurable difficulty curves, grid sizes, color counts, passenger-queue depths, and parking-slot configurations.
Three in-game boosters — Unlock Slot (opens a locked parking space), Shuffle (randomizes grid cars), and Balloon Pick (fly any car straight to a free parking slot) — with tutorial popups and usage tracking.
Ships with 100 pre-generated levels on a progressive difficulty curve, ready to play out of the box. Generate more at any time with the auto generator.
Provider-agnostic AdsManager facade with a Dummy provider out of the box. Plug in AdMob (or any SDK) in one file without touching gameplay code.
Edit > Project Settings > Graphics)Assets/CarParkingJam/Scenes/GameNew.unityOnce in Play mode, tap any clickable car on the grid (front-row cars and any car whose path to the front is clear). The car drives through the grid, out to the back row, then parks in the next free slot. Matching-colored passengers in the queues automatically walk over and board it. When every car is filled and all passenger queues are empty, the level is cleared and the next level loads automatically.
Each level features a grid of color-coded cars, a set of passenger queues above the grid, and a row of parking dock slots between them. The goal is to clear all passengers from the queues by filling every outgoing car with matching-colored passengers.
The game supports nine predefined car/passenger colors defined in the CarColor enum:
| Color Key | Color | Reference Hex |
|---|---|---|
Red |
Red | #FF4757 |
Green |
Green | #7BED9F |
Blue |
Blue | #48DBFB |
Yellow |
Yellow | #ECCC68 |
Orange |
Orange | #FFA502 |
Violet |
Violet | #BC8CFF |
Pink |
Pink | #FF6B81 |
Brown |
Brown | #A0522D |
Gray |
Gray | #A4B0BE |
The palette is defined by the Materials you assign to CarColorLibrary; the hex values above are the reference look used by the shipped art.
Passengers have three animation states: idle (waiting in the queue), run (walking from the queue to the docked car), and boarded (seated inside the car). Cars animate with smoothed path following, rotate toward their heading, and play a smoke-burst effect when the "hidden" cover is revealed. The Balloon Pick booster adds a rise → fly → drop sequence with a soft balloon sprite and particle plume.
Gameplay scripts live in the global namespace under Assets/CarParkingJam/Scripts/. Reusable engine scripts live in the same Assets/CarParkingJam/Scripts/ folder under the HypercasualGameEngine namespace.
| Script | Description |
|---|---|
ParkingGameManager |
The orchestrator. Tracks game state (stopGame, isPowerupActive, carMovingCount), bridges the engine LevelManager to ParkingLevelManager, wires booster callbacks, handles keyboard shortcuts, and triggers win/lose flow. |
ParkingLevelManager |
Static level loader. Loads every Level_N.json from Resources/Levels/, sorts by index, and tracks progression via the ParkingJam_CurrentLevel PlayerPrefs key. Exposes editor-only save/load helpers. |
ParkingLevelData |
Serializable POCO: grid size & spacing, cell list, passenger queue columns, parking slot count, locked-slot indices, waypoint paths, and per-level booster counts. |
ParkingLevelBuilder |
Builds the runtime scene from ParkingLevelData: spawns grid tiles, places cars, builds passenger queues, activates parking slots, applies locks, and lays out waypoints. Invoked on Start by BuildCurrentLevel(). |
ParkingLevelLoader |
Thin static helpers for scene reload, level advance, and jump-to-level. Used by win flow, dev panel, and keyboard shortcuts. |
CarGridBuilder |
Car-grid construction and lookup. Holds the 2D CarGridCell cache and exposes GetGridCell(col, row) / GetCar(col, row) to the rest of the system. |
CarGridCell |
Single grid cell. Stores row/column, occupancy flags (isOccupied, isEmpty, blockedPath), assigned CarColor, reference to the spawned car, and A*-style gCost used by pathfinding. |
ParkingCar |
Car entity. Handles OnMouseDown click routing, waypoint following, smoke/balloon effects, outline toggling, passenger counter display, parking finalization (SetParent + localPosition = zero), and reverse-move when a car re-enters the grid. |
ParkingSlotManager |
Parking-row state. Tracks parkingPositions, parkingStatus (per-slot color), maximumParkingCount, and lockedParkingSlots. Renders the gradient-glow effect on slot departure and the pop-scale animation on booster unlock. |
PathfindingManager |
Grid pathfinding. Maintains per-cell gCost, propagates costs outward from the front row, builds car paths on click, builds exit paths on departure, and updates reachability for hidden/blocked cars. |
PassengerGridBuilder / PassengerGridCell |
Construct the N-column, multi-row passenger grid with per-column spacing. Each cell stores row/column for queue-entry logic. |
PassengerMovement |
Passenger entity. Holds color + queue index, applies the correct material, and plays the walk → board animation sequence when summoned by PassengerQueueManager. |
PassengerQueueManager |
Coroutine TryBoardPassengers() scans each queue front against every docked car and sends matching passengers. Handles queue advance, queue empty detection, and level-win trigger. |
CarColor / CarColorLibrary |
The CarColor enum plus a ScriptableObject mapping each color to a car material and a passenger material. Used by every spawn path. |
HypercasualGameEngine)| Script | Description |
|---|---|
BoosterManager |
Reusable 3-booster manager. Handles lock/unlock by level, consume/refund counts, toggle mode (booster C), tutorial popups keyed in PlayerPrefs, and a 4-state HUD button UI (Locked / Usable / Depleted / Active). Exposes OnBoosterAUsed, OnBoosterBUsed, OnBoosterCActivated, OnBoosterCDeactivated for per-game wiring. |
LevelManager |
Generic level index tracker used by BoosterManager. ParkingGameManager mirrors ParkingLevelManager's index into it on Start, so booster unlock levels compare against the real parking level. |
LevelData |
Generic container for boosterACount/B/C. Registered in bulk from ParkingLevelData during the bridge. |
SoundManager |
Singleton audio facade. One AudioSource + PlayOneShot per call site. Exposes PlayCarTap, PlayCarPark, PlayCarExit, PlayWrongCar, PlayBlocked, PlayBooster, PlayPassengerBoard, PlayButtonClick, PlayLevelClear, PlayLevelFail. |
LoseWinPanelManager |
Win / lose panel controller. Auto-discovers child panels by name, drives the auto-advance coroutine, rotates the radial-shine decor, and wires the retry button. Patched to call ParkingLevelManager.AdvanceLevel() on next-level load. |
DeveloperModeButton / DeveloperSettingsController |
Corner Dev-Mode button toggles a panel with buttons for: next / previous / reload level, trigger win / lose, unlock all boosters, refill boosters, reset tutorial popups, visual theme cycling. |
AdsManager |
Provider-agnostic ads facade. ShowBanner, HideBanner, ShowInterstitial(onClosed), ShowRewardedVideo(onFinished), IsRewardedVideoReady. Ships with a Dummy provider — swap to AdMob in one file. |
MonetizationSettings |
ScriptableObject holding provider selection (Dummy / UnityAds / AdMob), platform-specific ad unit IDs, interstitial cadence, privacy & terms URLs. |
MonetizationInitModule |
Scene component: loads MonetizationSettings (inspector or Resources), boots AdsManager on Awake, optionally shows a banner immediately. |
| Script | Description |
|---|---|
ParkingLevelEditorWindow |
Unity Editor window (Tools > Car Parking Jam > Level Editor) for visually designing levels. Left panel lists levels with add / duplicate / reorder / delete / save-all. Right panel hosts grid painter, passenger-queue editor, parking slot count / lock editor, waypoint path editor, and booster-count fields. |
ParkingLevelGenerator |
Unity Editor window (Tools > Car Parking Jam > Auto Level Generator) for batch-generating levels with configurable difficulty curves. |
CarParkingJamWelcomePopup |
Welcome popup that appears on project open (via [InitializeOnLoadMethod]). Prompts for an Asset Store review and cross-promotes the HyperCasual Game Engine. Can be permanently dismissed. |
In the Unity menu bar, go to Tools > Car Parking Jam > Level Editor. This opens a dedicated Editor window — no need to enter Play mode.
| Mode | Left Click |
|---|---|
| None | No painting — click cells to inspect their contents |
| Place | Place a colored car at the clicked cell. Clicking an occupied cell replaces its color with the currently selected one. |
| Erase | Remove whatever car is at the clicked cell, leaving it empty. |
All levels are stored as individual JSON files in Assets/CarParkingJam/Resources/Levels/ with the naming convention Level_1.json, Level_2.json, etc. They are loaded at runtime via Resources.LoadAll<TextAsset>("Levels").
The Automatic Level Generator is an Editor tool that batch-generates playable parking-puzzle levels procedurally. It uses configurable difficulty curves, pathfinding-aware car placement, and balanced passenger-queue distributions to create varied, solvable levels.
In the Unity menu bar, go to Tools > Car Parking Jam > Auto Level Generator. This opens a settings window where you can configure all parameters before generating.
| Setting | Description |
|---|---|
| Levels to Generate | How many new level files to create. New levels are appended after existing ones (never overwrites). |
| Grid Rows / Columns (Min & Max) | Range for randomizing the grid dimensions of each level. Controls how much space cars have to route through. |
| Color Count (Min & Max) | Range for the number of distinct colors used per level. Default: 2–5. |
| Grid Fill (Min & Max) | Fraction of grid cells filled with cars. Higher fill = denser puzzle, tighter routing. |
| Hidden Car Ratio | Fraction of cars that start "covered". Revealed with smoke when reachable. |
| Passenger Queue Columns | Number of passenger queue columns above the parking row. Default: 3. |
| Passenger Queue Depth (Min & Max) | How many passengers stacked in each queue column. Sets total passengers per level. |
| Parking Slots (Min & Max) | Range for the number of parking dock slots per level. Default: 3–6. |
| Locked Slots (Min & Max) | Range for how many slots start locked. Only appear after the Locked-Slot intro level. Default: 0–1. |
| Lock Intro After Level | Locked slots only start appearing after this level number. Default: 10. |
| Booster Counts (Unlock / Shuffle / Balloon) | Min/Max booster uses per level. Inverted difficulty: more uses on early levels, fewer on harder levels. |
Resources/Levels/The generator never overwrites existing level files. It always starts numbering from the next available index (e.g., if Level_100 exists, new levels start from Level_101). Use the "Delete ALL Levels" button if you want to start fresh.
The game includes three booster abilities that players can activate during gameplay. Each booster has a configurable number of uses per level (set in the level JSON data) and an optional tutorial popup that appears on first use.
| Booster | Effect | Activation |
|---|---|---|
| Unlock Slot | Unlocks the leftmost locked parking slot, making it available for incoming cars. The lock icon fades out and the slot tile pops with a scale-bounce animation. Useful when all usable slots are full but locked ones remain. | Tap the Unlock button (Booster-Button-1). Consumes one use immediately. Automatically refunds the use if there are no locked slots to open. |
| Shuffle | Randomly rearranges every non-hidden car on the grid using a smooth arc-swap animation. Changes which cars are front-row and which paths are reachable, often turning a stuck board into a playable one. | Tap the Shuffle button (Booster-Button-2). Consumes one use immediately. |
| Balloon Pick | Activates a special toggle mode where the player can tap any non-hidden car on the grid, even one that would normally be blocked. The selected car lifts with a balloon, flies through the air, and drops into the next free parking slot. Its grid cell becomes empty and is re-propagated into the pathfinding map. | Tap the Balloon button (Booster-Button-3) to toggle the mode on. All non-clickable cars flash with a pulse to indicate they are now selectable. Tap again to cancel without consuming a use. A use is consumed only when you actually pick a car. |
Booster buttons are found in the GameHUD_Panel/BottomHolder in the scene UI. Each button has:
Bg) that shows/hides based on availabilityPowerUpCountText) showing remaining uses, or the unlock level if still lockedPress the U key during gameplay to unlock all boosters and refill their usage counts. Press Right Arrow / Left Arrow to jump to the next/previous level. These shortcuts are useful for testing.
To add a new car/passenger color:
CarColor.cs and add a new entry to the enum:
Art/Materials/ with the desired color, plus a matching passenger MaterialColorManger.asset (CarColorLibrary) ScriptableObject and add a new entry mapping CarColor.Teal to those materialsTools > Car Parking Jam > Level Editor > Save All to Disk so the JSON levels recognize the new color as a valid optionNew colors are automatically available in the Level Editor, Auto Level Generator, and at runtime.
The grid layout is controlled by CarGridBuilder and ParkingLevelBuilder. Key properties:
columnSpacing / rowSpacing (per level in JSON) — World-unit spacing between grid cellsgridTilePrefab / gridTileVisualPrefab — Tile mesh spawned per celltileMaterial — Shared material used for every grid tileCar rendering is handled by the ParkingCar component. Each car prefab includes:
CarColorLibraryCarOutline shader loaded from Resources; outline meshes are created/toggled dynamically by ParkingGameManager.UpdateCarOutlines()Passengers use SkinnedMeshRenderer with material coloring and Animator for character animations. To change the character model, replace the prefab mesh and ensure the Animator has triggers for the walk and seated states used by PassengerMovement.
Locked parking slots are indicated by a gray lock sprite overlay plus a dark-gray tile tint. Both are configured at runtime by ParkingSlotManager.ApplyLockedVisual(). To change the lock icon, replace the sprite on the Lock child of any Parking_Tile GameObject. To change the locked tile color, edit the LOCKED_TILE_COLOR constant in ParkingSlotManager.cs.
New boosters can be added by following the existing pattern in BoosterManager.cs:
HookUpExistingBoosters() following the HookUpBoosterButton() patternOnMyBoosterClicked())ParkingLevelData so it can be configured per level, and propagate it through the SyncEngineLevelManager() bridge in ParkingGameManagerUpdateBoosterUI() to handle the new booster's lock/unlock/count displayThe project ships with a stub AdsManager that runs in Dummy mode so the game works out of the box. To ship real ads:
MonetizationSettings asset: right-click in Assets/CarParkingJam/Resources/ → Create > Hypercasual > Monetization SettingsMonetizationInitModule component on a root GameObject in GameNew.unity and reference the assetDummy to AdMob and fill in your real ad-unit IDs (leaving Google's test IDs as placeholders during development)MODULE_ADMOB to Project Settings > Player > Scripting Define Symbols and wire the real SDK calls inside AdsManager.csGame code never imports GoogleMobileAds.* directly — it only calls AdsManager. This keeps the ad provider swappable in a single file.
Each level is a JSON file with the following structure:
The cells array defines grid cars (sparse: only non-empty cells). Each cell has row, column, cellType ("occupied" or "empty"), a carColor string matching the CarColor enum, and a hidden flag. The passengerQueues array has one entry per queue column with a list of color strings from front to back. lockedParkingSlots is a zero-indexed list of parking slot indices that start locked. The two path* arrays define the world-space waypoints cars follow from the grid to the parking row and from the parking row off-screen.
| Issue | Solution |
|---|---|
| No levels load / empty grid appears | Ensure JSON level files exist in Assets/CarParkingJam/Resources/Levels/ with the naming convention Level_1.json, Level_2.json, etc. Use the Auto Level Generator to create levels if the folder is empty. |
| Pink/magenta materials on objects | The project requires URP. Go to Edit > Project Settings > Graphics and ensure a URP Render Pipeline Asset is assigned. Check that the Settings/ folder contains valid URP assets. |
| Cars can't be clicked | Go to Project Settings > Player > Other Settings > Active Input Handling and set it to Both. Legacy OnMouseDown raycasts are disabled if you select "New Input System only". |
| Car outline not showing | The outline effect requires the CarOutline.shader file in Assets/CarParkingJam/Resources/. If missing, add it back or update ParkingCar.SetOutlineVisible() to use a different shader. |
| Passengers don't walk to cars | Check that PassengerQueueManager.TryBoardPassengers() is being triggered after every successful car park. Ensure queue columns are configured and the passengerQueues list in the level JSON is non-empty. |
| Booster buttons don't respond | Ensure the GameHUD_Panel/BottomHolder hierarchy contains children named Booster-Button-1, Booster-Button-2, and Booster-Button-3. Each needs a Button component. If you added a Canvas component for sorting order, you must also add a GraphicRaycaster. |
| Locked slot has no lock icon | Some Parking_Tile GameObjects in the scene may be missing their Lock child. ParkingLevelBuilder.EnsureLockIcon clones a sibling's Lock at runtime to handle this, but for a clean scene add a Lock child (matching the existing ones) under every Parking_Tile you want to be lockable. |
| 4th parking slot feels unusable | The slot is probably locked by the level JSON. Use the Unlock Slot booster in-game, or remove the index from lockedParkingSlots in that level's JSON file. |
| Level Editor shows empty grid | Click "Reload from Disk" in the Level Editor window, or ensure the Resources/Levels/ folder exists and contains valid JSON files. |
| Ads don't show at all | Confirm a MonetizationInitModule exists in GameNew.unity with a valid MonetizationSettings reference, and the providers are set to AdMob (not Dummy). Dummy mode only logs to the console. |
Resources/Levels/ folder regularlyIf you get stuck or have any issues, feel free to reach out to us at ragendom@gmail.com. We are happy to help!