# Editor-Setup (Meilenstein 0) Schritt-für-Schritt-Anleitung für die manuelle Editor-Arbeit aus `docs/ROADMAP.md`, Meilenstein 0: Szenen, Prefabs, NetworkManager. Referenz für Inspector-Feldnamen: Unity zeigt `_camelCase`-Felder ohne Unterstrich und mit Leerzeichen an (`_catalog` → **Catalog**, `_customerMask` → **Customer Mask**). --- ## 0. Ordner anlegen Im Project-Fenster unter `Assets/`: - `Assets/Scenes` - `Assets/Prefabs` - `Assets/Data` (falls noch nicht vorhanden) Rechtsklick auf `Assets` → `Create > Folder`, jeweils benennen. ## 1. Platzhalter-Produktkatalog Die Prefabs unten haben alle ein `Catalog`-Feld, das nicht leer sein darf (sonst NullReferenceException zur Laufzeit). Vollständige Produkte kommen später — jetzt nur ein leeres Katalog-Asset, damit referenziert werden kann: 1. Rechtsklick auf `Assets/Data` → `Create > AfterHours > Product Catalog` 2. Benennen: `ProductCatalog` Später Produkte anlegen (`Create > AfterHours > Product`) und in die `Products`-Liste dieses Assets ziehen. ## 2. Layer "Customer" anlegen Wird von `CustomerAgent` gebraucht (Personal-Space-Check per `OverlapSphere`). 1. `Edit > Project Settings > Tags and Layers` 2. Unter „Layers" eine freie User-Layer-Zeile (z. B. 6) mit `Customer` beschriften --- ## 3. Player-Prefab 1. `GameObject > Create Empty`, benennen `Player` 2. Component: `Character Controller` (wird von `PlayerAvatar` per `RequireComponent` verlangt) 3. Component: `Network Object` 4. Component: `PlayerAvatar` (aus `AfterHours.Networking`) 5. Component: `PlayerInteractor` (aus `AfterHours.Interaction`) 6. Component: `PlayerHands` (aus `AfterHours.Networking`) 7. Component: `Network Transform` — repliziert Position an andere Clients (für Solo-Host-Test egal, aber für Meilenstein 2 nötig) 8. Kind-Objekt für die Kamera: Rechtsklick auf `Player` → Kamera erstellen, benennen `CameraRoot`, auf Kopfhöhe positionieren (z. B. Y = 1,6) - `CameraRoot` in **beiden** Feldern eintragen: `PlayerAvatar.Camera Root` und `PlayerInteractor.Eyes` 9. Werte grob: `Walk Speed` 3.4, `Mouse Sensitivity` 2, `Reach` 2.5 (Defaults reichen) 10. `Interactable Mask` auf „Everything" lassen 11. Als Prefab nach `Assets/Prefabs` ziehen, Szenen-Objekt löschen ## 4. Customer-Prefab 1. `GameObject > Create Empty`, benennen `Customer` 2. Layer des Objekts auf `Customer` setzen 3. Component: `Nav Mesh Agent` 4. Component: `Capsule Collider` (Radius ~0.3, Height ~1.8) — ohne Collider erkennen sich Kunden nicht gegenseitig 5. Component: `Network Object` 6. Component: `Network Transform` (Server bewegt den Agent, muss an Clients repliziert werden) 7. Component: `CustomerAgent` (aus `AfterHours.Customers`) 8. `Catalog` → `ProductCatalog`-Asset 9. `Customer Mask` → Layer `Customer` 10. Optional: Platzhalter-Body (Capsule-Mesh als Kind), rein kosmetisch 11. Als Prefab nach `Assets/Prefabs` ziehen, Szenen-Objekt löschen ## 5. ShelfSlot-Prefab 1. `GameObject > Create Empty`, benennen `ShelfSlot` 2. Component: `Box Collider` (z. B. 0.5 × 0.8 × 0.4) — für den Blick-Raycast von `PlayerInteractor` 3. Component: `Network Object` 4. Component: `ShelfSlot` (aus `AfterHours.Shop`) 5. `Catalog` → `ProductCatalog`-Asset 6. `Capacity Units` Default (12) lassen 7. `Exposed To Street` nur bei vom Schaufenster sichtbaren Regalen anhaken (pro platzierter Instanz individuell) 8. `Display Root` optional (aktuell nur `// TODO` im Code) 9. Als Prefab nach `Assets/Prefabs` ziehen, Szenen-Objekt löschen ## 6. CashRegister-Prefab 1. `GameObject > Create Empty`, benennen `CashRegister` 2. Component: `Box Collider` 3. Component: `Network Object` 4. Component: `CashRegister` (aus `AfterHours.Shop`) 5. Kind-Objekt `QueueStart` (leeres Transform), vor der Kasse positioniert, `Forward`-Achse zeigt in Richtung der Warteschlange 6. `Catalog` → Asset, `Queue Start` → das `QueueStart`-Kind, `Queue Spacing` Default (0.8) 7. Als Prefab nach `Assets/Prefabs` ziehen, Szenen-Objekt löschen ## 7. StorageCrate-Prefab 1. `GameObject > Create Empty`, benennen `StorageCrate` 2. Component: `Box Collider` 3. Component: `Network Object` 4. Component: `StorageCrate` (aus `AfterHours.Shop`) 5. `Catalog` → Asset, `Product Id` → -1 bis ein echtes Produkt existiert (dann die ID eintragen), `Starting Quantity` Default (200) 6. Als Prefab nach `Assets/Prefabs` ziehen, Szenen-Objekt löschen Pro Produkt später vermutlich mehrere `StorageCrate`-Instanzen im Backroom — das Prefab ist die Vorlage, `Product Id` pro Instanz individuell setzen. ## 7b. OrderTerminal-Prefab Bestellt beim Großhandel nach — fixes Produkt/Menge pro Instanz, kein UI-Menü. 1. `GameObject > Create Empty`, benennen `OrderTerminal` 2. Component: `Box Collider` 3. Component: `Network Object` 4. Component: `OrderTerminal` (aus `AfterHours.Shop`) 5. `Catalog` → Asset, `Product Id` → ID eines existierenden Produkts, `Order Quantity` Default (50) 6. Als Prefab nach `Assets/Prefabs` ziehen, Szenen-Objekt löschen --- ## 8. Boot-Szene 1. `File > New Scene` (Basic/URP-Template), `File > Save As` → `Assets/Scenes/Boot.unity` 2. `GameObject > Create Empty`, benennen `NetworkManager` 3. Component: `Network Manager` 4. Component: `Unity Transport` — im `Network Manager`-Inspector unter „Network Transport" zuweisen 5. `Player Prefab` → `Player`-Prefab aus Schritt 3 zuweisen 6. `Customer`-Prefab registrieren (siehe Kasten unten) — `ShelfSlot`, `CashRegister`, `StorageCrate` **nicht** hier eintragen, die kommen als Szenen-Objekte direkt in die Shop-Szene 7. `Don't Destroy On Load` angehakt lassen (Default) — muss den Szenenwechsel zu `Shop` überleben 8. Component: `NetworkBootstrap` (aus `AfterHours.Networking`), `Game Scene Name` → `Shop` 9. Canvas + Buttons für Host/Join (siehe unten) ### Customer im Network Prefabs registrieren Das `Network Prefabs`-Feld im `NetworkManager` selbst nimmt nur Assets vom Typ *Network Prefabs List* auf (z. B. `DefaultNetworkPrefabs`), keine einzelnen Prefabs — deshalb taucht `Customer` dort nicht in einer Auswahl auf. 1. Im Project-Fenster die Datei `DefaultNetworkPrefabs` suchen (liegt meist direkt unter `Assets/`, wird vom NetworkManager automatisch angelegt) 2. Einmal draufklicken — der Inspector zeigt jetzt den Inhalt *dieses* Assets 3. Dort gibt es eine eigene Liste „Network Prefabs" mit einem `+`-Button 4. `+` klicken → neuer Eintrag mit leerem Prefab-Feld 5. `Customer`-Prefab aus `Assets/Prefabs` in dieses Feld ziehen Falls kein `DefaultNetworkPrefabs`-Asset existiert: Rechtsklick im Project-Fenster → `Create > Netcode > Network Prefabs List` (Menüpfad kann leicht abweichen), benennen, dann ins `NetworkManager`-Feld „Network Prefabs" ziehen. Prüfen falls es trotzdem nicht klappt: hat das `Customer`-Prefab wirklich eine `Network Object`-Component? (Prefab öffnen, Inspector prüfen.) ### Canvas mit Host/Join-Buttons 1. `GameObject > UI > Canvas` (legt automatisch ein `EventSystem`-Objekt mit an — nicht löschen) 2. Canvas auswählen, `GameObject > UI > Button` (ggf. Popup „Import TMP Essentials" bestätigen) 3. Umbenennen zu `HostButton`, im linken Bereich des Canvas positionieren 4. Beschriftung: Kind-Objekt `Text (TMP)` anklicken, Text-Feld auf „Host" ändern 5. Schritte 2–4 wiederholen für `JoinButton` mit Text „Join" 6. `HostButton` auswählen → Inspector → `Button (Script)` → Bereich „On Click ()" 7. `+` klicken → neuer Listeneintrag mit leerem Objektfeld 8. Das GameObject mit der `NetworkBootstrap`-Component reinziehen (das `NetworkManager`-Objekt aus Schritt 8.2) 9. Dropdown „No Function" → `NetworkBootstrap` → `HostGame ()` auswählen 10. Gleiches für `JoinButton`, aber `JoinGame ()` --- ## 9. Shop-Szene 1. `File > New Scene`, `File > Save As` → `Assets/Scenes/Shop.unity` 2. Grobes Blockout bauen (siehe unten) 3. `Floor` auswählen → `Add Component` → `Nav Mesh Surface` hinzufügen (Component aus `com.unity.ai.navigation` — ersetzt das alte, deprecated `Static > Navigation Static`-Flag) 4. Defaults meist ok (Agent Type: Humanoid, Collect Objects: All, Include Layers: Everything) — Wände blockieren dank ihrer Collider automatisch. Ganz unten in der Component auf `Bake` klicken (ohne das läuft kein `NavMeshAgent`) 5. Zwei leere GameObjects: `EntryPoint`, `ExitPoint`, in der Türlücke platziert 6. `GameObject > Create Empty` → `GameClock`, Components `GameClock` + `Network Object` 7. `GameObject > Create Empty` → `ShopEconomy`, Components `ShopEconomy` + `Network Object` 8. `GameObject > Create Empty` → `CustomerSpawner`, Components `CustomerSpawner` + `Network Object` 9. `GameObject > Create Empty` → `SupplierService`, Components `SupplierService` (aus `AfterHours.Economy`) + `Network Object`. `Catalog` → Asset, `Delivery Lead Hours` Default (4) — bei Standard-`GameClock`-Tempo (60 reale Sekunden = 1 Spielstunde) entspricht das 4 realen Minuten bis zur Lieferung, zum Testen ggf. runterdrehen 10. `ShelfSlot`-, `CashRegister`-, `StorageCrate`- und `OrderTerminal`-Prefabs aus dem Project-Fenster in die Szene ziehen und platzieren (2–3 Regale reichen fürs Erste) 11. `CustomerSpawner` verkabeln: `Customer Prefab` → Customer-Prefab, `Entry Point`/`Exit Point` → die beiden Transforms, `Register` → platzierte CashRegister-Instanz 12. **Wichtig:** `GameClock`, `ShopEconomy`, `CustomerSpawner`, `SupplierService`, `ShelfSlot`-, `CashRegister`-, `StorageCrate`- und `OrderTerminal`-Instanzen sind direkt in der Szene platziert ("in-scene placed NetworkObjects") — NGO spawnt sie automatisch, wenn der Server die Szene lädt. Keine Registrierung in der Network Prefabs List nötig (anders als beim `Customer`-Prefab). ### Grobes Blockout **Boden:** 1. `GameObject > 3D Object > Plane`, benennen `Floor` 2. Position `(0, 0, 0)`. Standardgröße 10×10 Units (Meter) reicht fürs Erste; Scale anpassen für andere Größe (z. B. `1.5, 1, 1` für 15×10m) **Wände:** 1. `GameObject > 3D Object > Cube`, benennen `Wall_North` 2. Transform: Position `(0, 1.5, 5)`, Scale `(10, 3, 0.2)` 3. 3× duplizieren (`Ctrl+D`), neu positionieren: - `Wall_South`: Position `(0, 1.5, -5)`, Scale gleich - `Wall_East`: Position `(5, 1.5, 0)`, Scale `(0.2, 3, 10)` - `Wall_West`: Position `(-5, 1.5, 0)`, Scale `(0.2, 3, 10)` 4. Für einen Eingang: eine Wand (z. B. `Wall_South`) durch zwei kürzere Cubes ersetzen (Scale `(4, 3, 0.2)`) mit ca. 2m Lücke dazwischen als Tür Cube-/Plane-Primitives bekommen automatisch einen passenden Collider — nichts extra nötig. **Aufräumen (optional):** `GameObject > Create Empty` → `Blockout`, `Floor` + alle `Wall_*` per Drag & Drop als Kinder reinziehen. Wände brauchen keine eigene `Nav Mesh Surface`/Modifier-Component — sie blockieren das NavMesh automatisch über ihre Collider, solange sie im „Include Layers"-Bereich der `Nav Mesh Surface` auf `Floor` liegen (Default: Everything). Farbe/Material ist rein kosmetisch, kann später kommen. --- ## 10. Build Settings `File > Build Settings` (bzw. `Build Profiles` in Unity 6) → „Add Open Scenes" für beide Szenen, `Boot` an Index 0. ## 11. Testen 1. `Boot`-Szene öffnen, Play drücken 2. „Host" klicken → sollte automatisch in die `Shop`-Szene wechseln 3. Mit WASD/Maus bewegen 4. Regal anschauen, `E` am `StorageCrate` (Ware aufnehmen), dann am `ShelfSlot` (einräumen) 5. Warten, bis ein Kunde spawnt: läuft er zum Regal, nimmt Ware, stellt sich an? An der Kasse `E` zum Scannen/Kassieren 6. Am `OrderTerminal` `E` drücken → Guthaben (`ShopEconomy.Balance`, aktuell nirgends im UI sichtbar, ggf. Inspector der `ShopEconomy`-Instanz während Play beobachten) sollte sofort sinken. Nach `Delivery Lead Hours` Spielstunden sollte die Menge in der passenden `StorageCrate` steigen Bei Problemen: genauer Fehler bzw. Console-Meldung notieren, dann gezielt nachschauen.