chore: add project scaffolding, third-party assets and settings

- Terrain, Prefabs, Textures, Modelle (u. a. Lieferkarton-/Vibrations-
  Rohdaten in Assets/Data)
- Third-Party-Pakete: TextMesh Pro, Toby Fredson Foliage Engine, Sat
  Productions Street Lights, ProBuilder Data
- Neue Szene Boot.unity, Shop-Szenenordner
- Package-Manifest/Lock, ProjectSettings, Build-Profile, .slnx
- Doku: EDITOR_SETUP.md, INSTALL.md, TODO.md

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-14 19:22:02 +02:00
co-authored by Claude Sonnet 5
parent 7e4cebbf13
commit 2fd424b2bf
1156 changed files with 2492022 additions and 12 deletions
+216
View File
@@ -0,0 +1,216 @@
# 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 24 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 (23 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.