Guide 17 — Store Simulator

Sanad Ammari


What you're building

A first-person shop management sim in the tradition of Supermarket Simulator and Gas Station Simulator. Order stock, carry boxes, fill shelves, serve customers at the register, pay the rent, and try to still be in business tomorrow.

Yours is the only fully 3D game in the class, and the only one that needs a baked NavMesh — which is worth knowing up front because it's the one step where nothing works at all until it's done.

Time: about four hours. The NavMesh and the first-person setup are front-loaded; once customers walk, the rest goes quickly.


1. Before you start


2. Scripts you'll use

The store (Tier 7)
FirstPersonController · ProductType · Carryable · PickupCarry · ShelfSlot · StoreEconomy · CustomerAI · Register · CustomerSpawner

Core
GameManager · SceneLoader · AudioManager · HUDController · ChoiceFlagManager

Saving (Tier 7)
SaveData · SaveSystem

Interaction (Tier 6)
Interactable · InteractionPrompt — optional, for a shop terminal

You will not need: anything 2D. No PlayerController2D, no Health, no combat, no hazards.


3. Build the store and bake the NavMesh

Do this first. Customers are your entire game and they cannot move one centimetre without it.

The room

  1. GameObject → 3D Object → Plane, name it Floor. Scale it to about (3, 1, 3) — that's a 30×30 metre shop.
  2. Walls: 3D Object → Cube, scaled thin and tall, around the edges. Leave a gap for the door.
  3. Shelves: cubes for now. Grey boxes are fine — you're testing whether customers can walk, not how it looks.

Bake it

  1. Window → AI → Navigation. (Unity 6 with the AI Navigation package: instead select the Floor and Add Component → NavMeshSurface.)
  2. With NavMeshSurface on the floor, click Bake.
  3. You should see a blue overlay on the walkable area of your floor. Walls and shelves should be cut out of it.

If there's no blue

Problem Fix
Nothing bakes at all The floor has no NavMeshSurface, or you clicked Bake on the wrong object
Blue covers the shelves Shelves need colliders — a Cube has one by default; check they're not disabled
Blue doesn't reach the corners Agent Radius is too large in the bake settings — lower it to 0.3
Blue is patchy Your floor is made of many small objects with gaps between them

Do not proceed until you see blue. Everything after this depends on it.


4. Build the player

3D, so this is different from every other guide.

  1. GameObject → Create Empty, name it Player. Tag → Player.
  2. Add a CharacterController:
Setting Value
Height 1.8
Radius 0.3
Center (0, 0.9, 0)
  1. Add Player Input — Behavior: Send Messages, Default Map Player.
  2. Add FirstPersonController:
Field Value
Walk Speed 3.5
Sprint Speed 6
Crouch Speed 1.8
Gravity −20
Jump Height 1.1
Camera Pivot see step 5
Mouse Sensitivity 0.12
Stick Sensitivity 120
Min / Max Pitch −80 / 80
Stand Height 1.8
Crouch Height 1.1
Lock Cursor ✓
  1. Right-click Player → Create Empty, name it CameraHolder, position (0, 1.6, 0). Drag your Main Camera inside it, at local position zero. Drag CameraHolder into Camera Pivot.
  2. Right-click CameraHolder → Create Empty, name it CarryPoint, position (0, −0.2, 0.8) — in front of and slightly below the camera.

Escape releases the cursor. Useful in the editor. If you add a pause menu, wire it to FirstPersonController.UnlockCursor.

Press Play now. You should be able to walk and look around.


5. Create your products

Right-click Project → Create → GAME1303 → Product, once per item you'll sell.

Example: Milk

Field Value
Display Name Milk
Icon a sprite, optional
World Prefab see below
Wholesale Price 1.00
Retail Price 2.00
Units Per Box 12
Popularity 2 (popular)
Price Tolerance Multiplier 1.5

A starting range

Product Wholesale Retail Per Box Popularity
Milk 1.00 2.00 12 2
Bread 0.80 1.75 10 2
Batteries 2.50 5.00 8 1
Cleaning spray 1.50 3.25 6 1

The gap between wholesale and retail is your entire economy. A box of milk costs 12 units × £1 = £12 and sells for £24. That £12 margin has to cover the rent.

The product prefab

  1. GameObject → 3D Object → Cube, scale it to roughly the item's size (milk: 0.1 × 0.2 × 0.1).
  2. Add a Rigidbody and keep its Box Collider.
  3. Layer → Carryable.
  4. Add Carryable:
Field Value
Product the ProductType asset
Units −1 (means "use the product's Units Per Box")
Can Be Picked Up ✓
Destroy When Empty ✓
  1. Save as a prefab and drag it into the ProductType's World Prefab slot.

One prefab does double duty: it's the box you carry and the item that appears on the shelf. ShelfSlot disables physics on the display copies.


6. Carrying

On Player, add PickupCarry:

Field Value
Carry Point the CarryPoint child
View Camera your Main Camera
Reach 2.5
Carryable Layers Carryable
Can Throw ✓
Throw Force 6
Place Distance 1.2
Pickup Sfx pickup
Drop Sfx drop

Add the Pickup input action (bind E). Throwing uses the existing Attack action (left mouse).

How it plays: look at a box within 2.5m, press E to pick it up, press E again to put it down, left-click to throw it.


7. Shelves

  1. Empty GameObject ShelfSlot_Milk positioned on a shelf.
  2. Add a Box Collider roughly the size of the shelf space (not a trigger — the player's ray needs to hit it).
  3. Right-click it → Create Empty, name it ItemAnchor, at the back-left of the slot.
  4. Add ShelfSlot:
Field Value
Assigned Product Milk (or leave empty for "any")
Capacity 12
Units Per Press 3
Item Anchor the child
Columns / Rows 3 / 2
Spacing (0.25, 0.25, 0.25) — tune to your item size
Look Range 3
Stock Sfx stock
  1. Save as a prefab and place several, assigning a different product to each.

How it plays: carry a matching box, look at the shelf, press E. Three units transfer per press and appear as visible objects. Keep pressing until the box is empty or the shelf is full.

Units Per Press 3 is a pacing decision. At 1 it's tedious; at 12 it's instant and unsatisfying. Three presses to empty a twelve-unit box feels like work without being a chore — which is exactly the tone of the genre.


8. The register

  1. A cube or model for the counter, named Register.
  2. Add a Box Collider.
  3. Right-click → Create Empty, name it QueueStart, positioned in front of the counter where the first customer stands.
  4. Another empty called PlayerStandZone behind the counter, with a Box Collider, Is Trigger ✓, big enough to stand in.
  5. Add Register:
Field Value
Queue Start the QueueStart child
Queue Spacing 0.8
Queue Direction (0, 0, −1) — the way the queue extends back
Max Queue 6
Player Stand Zone the trigger collider
Scan Time 0.4
Auto Serve ✓ while testing, ✗ later
Auto Serve Delay 2
Scan Sfx beep
Cash Sfx cash

How it plays: stand inside the zone behind the counter, press E once per item in the customer's basket. When you've scanned everything, they pay and leave.

Auto Serve ✓ while testing means sales happen without you, so you can watch the economy work before building the interaction. Turn it off once customers are queuing properly.

The cyan gizmo spheres show where the queue will form. Check they aren't inside a wall.


9. Customers

The prefab

  1. GameObject → 3D Object → Capsule, name it Customer.
  2. Add a NavMeshAgent:
Setting Value
Radius 0.3
Height 1.8
Speed 2
Angular Speed 200
Acceleration 8
Stopping Distance 0.5
  1. Add CustomerAI:
Field Value
Shopping List Size 2
Patience Seconds 25
Pickup Time 1.5
Register leave empty — it finds it
Store Exit assigned by the spawner
  1. Save as a prefab. Make two or three with different capsule colours so the shop doesn't look cloned.

The spawner

  1. Empty GameObject Spawner at the shop door, on the NavMesh.
  2. Empty GameObject StoreExit at the same door.
  3. Add CustomerSpawner:
Field Value
Customer Prefabs your customer prefabs
Register the Register
Store Exit the StoreExit
Seconds Between Customers 12
Variance 4
Max In Store 6
Start Delay 5
Scale With Day ✓
Rate Improvement Per Day 0.8
Minimum Interval 3

What a customer does

Walks in → picks 2 products (weighted by Popularity) → walks to a stocked shelf → takes one → repeats → queues at the register → waits for you → pays → leaves. If a shelf is empty and stays empty past their patience, they leave unhappy.

OnLeftUnhappy is your most important feedback. Wire it to a sound — it's how the player learns to restock without being told.


10. The economy

  1. Empty GameObject StoreEconomy + the component.
  2. Empty GameObject DeliveryPoint near the back door, on the NavMesh.
Field Value
Starting Cash 200
Daily Rent 50
Use Day Cycle ✓
Day Length Seconds 300 (5 minutes)
Delivery Point the DeliveryPoint
Delivery Delay 5

Ordering stock

StoreEconomy.OrderBox(product) spends wholesale × unitsPerBox and delivers a box after 5 seconds. To let the player order, make a simple shop UI:

  1. Canvas → Panel ShopPanel, hidden by default.
  2. One Button per product, labelled Milk — £12.
  3. Each Button's On Click → StoreEconomy.OrderBox, then drag the ProductType asset into the parameter slot.
  4. A Button somewhere to toggle the panel.

Or: put an Interactable on a back-room computer that opens the panel. More diegetic, same wiring.

Tuning the difficulty

Starting Cash 200, rent 50 per day, a milk box costing 12 and returning 24. That means roughly five boxes sold per day just to cover rent. Tight — deliberately.

The reference games work because money is tight at the start. If your first playtest feels comfortable, lower Starting Cash rather than raising rent; running out of runway is more interesting than a big bill.


11. The HUD

  1. Canvas → CashText (£200.00), top-right.
  2. DayText (Day 1), below it.
  3. DayProgressBar — a Slider, Min 0 / Max 1.
  4. CarryText — centre-bottom, shows what you're holding.
  5. A crosshair — a small dot Image in the centre.
  6. Empty child HUD with HUDController (most of its fields stay empty; your game has no health).

Text wiring note: OnCashChanged sends a float and OnDayChanged an int; TMP's text wants a string, so they don't connect directly. Ask your instructor for a small display script — one that takes a float and formats it as currency. It's about four lines and you'll use it for cash, day, and the carry readout.

The day progress bar works with no script: OnDayTimeChanged sends a 0–1 float straight into Slider.value.


12. Wire it up

On this object Event Drag in Choose
StoreEconomy On Day Time Changed DayProgressBar Slider.value (Dynamic float)
StoreEconomy On Day Ended AudioManager PlaySFX (string) → day_end
StoreEconomy On Went Broke GameManager GameManager.GameOver
StoreEconomy On Delivered AudioManager PlaySFX (string) → delivery
Register On Customer Waiting AudioManager PlaySFX (string) → bell
Register On Sale Completed AudioManager PlaySFX (string) → cash
Customer prefab → CustomerAI On Left Unhappy AudioManager PlaySFX (string) → unhappy
Each shop Button On Click StoreEconomy StoreEconomy.OrderBox → drag the ProductType in

Row 5 is the heartbeat of the genre. A bell when someone reaches the till is what pulls the player away from stocking shelves. Without it they'll never know they're needed.


13. First playtest

Turn Auto Serve on for this.

  1. You can walk and look. Escape releases the cursor.
  2. A box spawns at the delivery point when you order one (test with a button, or place one by hand).
  3. You can pick it up — look at it, press E.
  4. You can stock a shelf — carry a matching box, look at the slot, press E. Items appear.
  5. The box empties and disappears after four presses.
  6. A customer walks in — if they spawn and stand still, your NavMesh isn't baked or the spawner is off it.
  7. They walk to a stocked shelf and take an item.
  8. They queue at the register.
  9. With Auto Serve on, they pay and leave, and cash goes up.
  10. An empty shelf makes them leave unhappy after 25 seconds.
  11. The day ends after 5 minutes and rent is deducted.

Then turn Auto Serve off and check step 9 again with you standing behind the counter pressing E.


14. Then add

  1. Art. Grey boxes get you here; shelves, products and a shop interior make it a game. This is your biggest remaining job.
  2. More products — each one is just a ProductType and a prefab.
  3. A back room with the delivery point and the ordering computer.
  4. SaveSystem — tick Save Flags and Save Collectibles, and add a ChoiceFlagManager. Cash and day would need a small addition; ask if you want it.
  5. Price setting — letting the player choose retail prices, with customers refusing above the tolerance multiplier. Needs a small UI and a script.
  6. A day-end summary panel — wire OnDayEnded to show revenue and expenses.

15. Design notes for your game specifically

Bake the NavMesh before anything else, and re-bake after moving walls. It's static geometry — if you rearrange the shop, the old NavMesh stays until you bake again. "Customers walk through the new shelf" always means a stale bake.

The genre runs on interruption. Stocking shelves is calm, repetitive, satisfying work. The bell at the register interrupts it. That tension — wanting to finish the box you're holding while someone waits — is the gameplay. Make the bell audible and the register visible from the shelves.

Money must be tight at the start. Every game you listed works because the first delivery is a real decision. Five boxes a day just to cover rent means the player has to think about what sells. If it feels safe in playtesting, cut Starting Cash to 150.

Popularity is your cheapest design lever. A product with Popularity 3 sells constantly and a Popularity 1 product gathers dust. That teaches the player to read demand without any tutorial — and adjusting one number rebalances your whole shop.

Scale With Day is your entire progression curve. At 0.8 seconds shaved per day, day 10 has customers arriving twice as fast as day 1. That single float is what makes the game get harder, and it's worth playing with more than almost anything else here.

Auto Serve is a genuine testing tool, not a shortcut. Use it to check whether your prices, rent and spawn rate produce a survivable but tense economy. Once the numbers work, turn it off and the game is about you keeping up with them.


16. Common problems

What you see What's wrong
Customers spawn and don't move NavMesh not baked — this is almost always it
Customers walk through shelves Stale bake — re-bake after moving anything
Customers can't reach a shelf The shelf sits off the NavMesh, or is surrounded by other colliders
Customer spawns then vanishes Spawner isn't on the NavMesh
Can't pick up boxes Box not on the Carryable layer, or Carryable Layers unset, or no Carryable component
Box picked up but invisible CarryPoint is inside the camera's near clip — move it further forward
Can't stock a shelf Product doesn't match Assigned Product, or the shelf has no collider, or you're beyond Look Range
Items don't appear on the shelf ProductType has no World Prefab, or Item Anchor unassigned
Items on the shelf fall off They shouldn't — ShelfSlot disables their physics. If they do, the display copies aren't being created by the slot
Register does nothing PlayerStandZone unassigned or you're outside it; or no customer is queuing
Queue forms inside a wall Queue Direction points the wrong way — check the cyan gizmos
Cash never changes Sales aren't completing; turn on Auto Serve to isolate
Game over immediately Starting Cash lower than the first rent payment
Mouse won't move the view Look action missing, or the cursor isn't locked — click in the game view

17. Checklist