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.
+59
View File
@@ -0,0 +1,59 @@
# Package-Installation — Referenz
Notizen zu Packages, die nicht über den normalen „Package Manager suchen →
Install"-Weg liefen. Für alles andere reicht: `Window > Package Manager`
oben links auf „Unity Registry" stellen → Name eintippen → `Install`.
## Netcode for GameObjects (NGO)
- Paket-ID: `com.unity.netcode.gameobjects`
- Verwendete Version: `2.13.1`
**Besonderheit:** Ältere Versionen (getestet: `2.2.0`) verwenden intern
bereits als `error` markierte, veraltete Unity-APIs (`GetInstanceID()`,
`SceneHandle`-Konvertierung) — das bricht die Kompilierung unter neueren
Editor-Versionen (bei uns 6000.5.7f1). Falls NGO mal wieder Compile-Fehler
aus dem `Library/PackageCache/com.unity.netcode.gameobjects@...`-Ordner
wirft: aktuellste verfügbare Version über den Package Manager ziehen, nicht
auf einer alten Version bestehen.
Aktuelle Version prüfen: `https://packages.unity.com/com.unity.netcode.gameobjects`
## ProBuilder
- Paket-ID: `com.unity.probuilder`
- Verwendete Version: `6.1.2`
- Ganz normal über die Registry-Suche installierbar, kein Sonderfall.
## ProGrids
- Paket-ID: `com.unity.progrids`
- Verwendete Version: `3.0.3-preview.6`
**Besonderheit:** Von Unity nicht mehr aktiv beworben — taucht in der
durchsuchbaren Package-Manager-Liste meist gar nicht auf, auch nicht mit
aktivierten Preview-Paketen. Installation nur über den direkten Weg:
1. `Window > Package Manager`
2. Oben links auf das `+`-Icon klicken
3. „Add package by name..." auswählen
4. Name: `com.unity.progrids`, Version: `3.0.3-preview.6``Add`
## Polybrush
- Paket-ID: `com.unity.polybrush`
- Verwendete Version: `1.2.1`
**Besonderheit:** Gleiches Problem wie ProGrids — taucht nicht in der
Suche auf, nur über „Add package by name" installierbar:
1. `Window > Package Manager``+`-Icon → „Add package by name..."
2. Name: `com.unity.polybrush`, Version: `1.2.1``Add`
## Genereller Trick
Wenn ein Package partout nicht in der Suche auftaucht, aber die Paket-ID
bekannt ist: immer `+` → „Add package by name..." probieren, statt zu
suchen. Aktuelle Version eines Pakets lässt sich vorab prüfen unter
`https://packages.unity.com/<paket-id>` (liefert JSON mit allen
verfügbaren Versionen).
+50
View File
@@ -0,0 +1,50 @@
# TODO — aktueller Stand
Kurzfristige, konkrete Punkte aus der laufenden Arbeit. Für den groben
Fahrplan siehe `docs/ROADMAP.md`, für die Editor-Klickpfade `docs/EDITOR_SETUP.md`.
## Editor-Setup, noch offen
- [ ] ProBuilder installieren (`Window > Package Manager` → Unity Registry → „ProBuilder")
- [ ] `OrderTerminal`-Prefab bauen (Anleitung: `EDITOR_SETUP.md` Schritt 7b)
- [ ] `SupplierService`-Objekt in der `Shop`-Szene anlegen (Schritt 9.9)
- [ ] `OrderTerminal`-Instanz platzieren, `Product Id` auf ein echtes Produkt setzen
## Content
- [ ] Weitere `ProductDefinition`-Assets anlegen — laut `ROADMAP.md` Meilenstein 0 sollten es 810 sein, bisher nur 1 erstellt
- [ ] Für zuverlässiges Kunden-Testing: mind. 23 Regale mit unterschiedlichen `Category`-Werten bestücken (Kunden wollen zufällig eine von 5 Kategorien)
## Testen
- [ ] Kompletten Golden Path einmal durchspielen und bestätigen: Kunde spawnt → läuft zum Regal → nimmt Ware → stellt sich an → wird kassiert → verlässt den Laden (bisher nur einzelne Teilschritte verifiziert, nicht der volle Ablauf am Stück)
- [ ] Bestell-/Lieferfluss testen: `OrderTerminal` per `E` → Guthaben sinkt sofort → nach `Delivery Lead Hours` Spielstunden steigt die Menge in der passenden `StorageCrate`
## Aufräumen
- [ ] Debug-`Log`-Zeilen wieder entfernen, sobald Zielerkennung + Regal-Befüllen zuverlässig laufen (markiert mit `// TODO` in `PlayerInteractor.cs` und `ShelfSlot.cs`)
## Bekannte Lücken seit Meilenstein 1
Im Code als `// TODO` markiert oder beim Testen aufgefallen — bewusst nicht
für den vertikalen Schnitt behoben, aber vor Meilenstein 2 (Koop) bzw.
weiterer Content-Arbeit relevant:
- [ ] `CustomerAgent.IsStaffCrowding()` liefert immer `false` — Personal-Nähe-Check für den Komfort-Wert fehlt noch (`CustomerAgent.cs:186`)
- [ ] `CustomerAgent.Abandon()` schreibt aufgegebene Warenkorb-Ware nicht zurück ins Regal — Ware ist beim Abbruch einfach weg (`CustomerAgent.cs:202`)
- [ ] `GameClock.SkipToOpening()` ("Feierabend"-Button) prüft nicht, ob noch Kunden im Laden sind, bevor der Tag springt (`GameClock.cs:68`)
- [ ] Kunden, die dauerhaft kein passendes Regal finden (Kategorie nirgends vorrätig), bleiben für immer stehen — kein Timeout/Aufgeben-Mechanismus
- [ ] Kein Fadenkreuz/Crosshair und kein echter Prompt-Text im UI — `PlayerInteractor.CurrentPrompt` wird berechnet, aber nirgends angezeigt
- [ ] Keine visuelle Rückmeldung, was der Spieler gerade trägt (`PlayerHands` hat keine Darstellung)
- [ ] `ShelfSlot.RefreshVisuals()` ist leer — keine Verpackungs-Darstellung im Regal je nach Menge (`ShelfSlot.cs:129`)
## Meilenstein 3 — noch offen (nach Bestellsystem)
- [ ] Tagesabrechnung, Miete, Personalkosten (baut auf `GameClock.DayEnded` + `ShopEconomy` auf)
- [ ] Beratungs-Minispiel (Kundenandeutung → passende Kategorie)
- [ ] Laden-Upgrades (Umkleide, Vorhang, zweite Kasse, Regalreihen)
- [ ] Sichtachsen-System (`ExposedToStreet` automatisch aus Geometrie ableiten)
## Im Hinterkopf behalten
- Meilenstein 2 (Koop) kommt erst später, aber neue Systeme sollten schon jetzt server-authoritativ und race-condition-bewusst gebaut werden (siehe CLAUDE.md §3) — ist bei `SupplierService`/`OrderTerminal` bereits berücksichtigt