Cozy Wather + buld systeme
This commit is contained in:
+51
-4
@@ -51,9 +51,20 @@ Context for current work:
|
||||
per-player networked state, which belongs on a `NetworkBehaviour` (SyncVar/RPC), not the
|
||||
bus (see §3).
|
||||
|
||||
**Each script owns one concern.** A script reads its own inputs/state from the bus,
|
||||
does its job, and raises events for others. Do not let a script mutate another system's
|
||||
internal data directly. If two systems need to coordinate, route it through `PlayerEvents`.
|
||||
**Each script owns one concern — but "concern" means one reason to change, not one tiny
|
||||
action.** A script reads its own inputs/state from the bus, does its job, and raises events for
|
||||
others. Do not let a script mutate another system's internal data directly. If two systems need
|
||||
to coordinate, route it through `PlayerEvents`.
|
||||
|
||||
Group by **cohesion, not by a per-action counter.** Splitting a feature into many micro-scripts
|
||||
is its own anti-pattern (scattered logic, high coupling, inspector-wiring noise) just as much as a
|
||||
god-object is. Keep together what changes together and is used together; split only at a **real
|
||||
seam** — a genuinely different reason to change, a different collaborator set, or a file growing
|
||||
unwieldy. The seam that always matters: **local player UX vs shared networked state** (see §3) —
|
||||
never fuse across it. Reference: the build system splits into `BuildManager` (all the *local*
|
||||
build UX — catalog, menu, placement) and `BuildRegistry` (the *networked* side — committed
|
||||
structures + the ghost NetworkObject), one clean local/network seam, not a script per
|
||||
sub-responsibility.
|
||||
|
||||
Data that is authored in the editor lives in **ScriptableObjects** (`ItemData`,
|
||||
`CraftingRecipe`, `SurfaceSoundProfile`, `ScatterProfile`, `MusicPlaylist`,
|
||||
@@ -63,6 +74,20 @@ Singletons exist where a single instance is genuinely global (`PlayerInventory.I
|
||||
`PlayerStats.Instance`, …); guard every access for `null` — they may not exist yet or in
|
||||
every scene.
|
||||
|
||||
**UI is a dumb view — a manager owns the data and populates it.** A UI component (a panel,
|
||||
a card, a list row, …) must **never** reach for domain data itself: no catalog, no
|
||||
`ScriptableObject` list, no scanning a database/model to decide *what* to show. It exposes a
|
||||
`Populate(...)` / `Set(...)` method that takes a lightweight **view payload** (plain
|
||||
icon / label / number data — never the authored `ScriptableObject`) plus a selection
|
||||
callback, and renders exactly what it is handed. A dedicated **manager** owns the real data
|
||||
(the catalog, the model), builds the view payload, pushes it into the UI, and handles the
|
||||
callback — i.e. it decides what a click *does*. The view reports interactions back by
|
||||
**index or token**, never by resolving the underlying data. Data flows one way (manager →
|
||||
view), interactions flow back one way (view → manager via callback), and views stay
|
||||
swappable and data-agnostic. Reference implementation: `BuildManager` (owns the catalog,
|
||||
populates + handles picks) + `BuildMenuUI` / `BuildMenuCardUI` (pure views) +
|
||||
`BuildCardView` (the view payload).
|
||||
|
||||
---
|
||||
|
||||
## 3. Multiplayer — the second golden rule
|
||||
@@ -90,6 +115,21 @@ player — get it from `PlayerInventory.Instance` / `PlayerStats.Instance` (owne
|
||||
singletons), **never** `FindObjectOfType<PlayerX>()`, which also matches disabled remote
|
||||
puppets (their root GameObject stays active) and targets the wrong player.
|
||||
|
||||
### Keep systems OFF the player — it holds only its own intrinsic state
|
||||
|
||||
**Default to a scene object/registry, not the player prefab.** The player carries *only what is
|
||||
intrinsically the local player itself*: its owner-only local simulation (input, locomotion, camera,
|
||||
tools, animation driver) and its own per-player networked state (health/stats, inventory, the body).
|
||||
**Everything that touches the world or shared state — and anything that does not need per-player
|
||||
networking — lives OUTSIDE the player.** This is logical: a build, a placed structure, a shared
|
||||
station, even a *per-player preview of a world action* (the build ghost), is world-facing, so it
|
||||
belongs to a scene `NetworkBehaviour` (a `SyncList<…>` registry, or a NetworkObject it spawns),
|
||||
**never bolted onto the player**. Do not reflexively put per-player networked state on the player
|
||||
just because it is "per player" — ask first *"is this the player, or is it the world?"*. If it is
|
||||
world/shared, it is a scene object. Reference implementations: `WorldObjectRegistry`, `BuildRegistry`
|
||||
(committed structures + the spawned ghost preview), `CookingStation`. The player-hosted pattern
|
||||
below is only for state that genuinely *is* the player.
|
||||
|
||||
### Visible body — first-person arms (owner) + third-person body (remotes)
|
||||
|
||||
Every player is drawn twice, split by viewpoint (see §1):
|
||||
@@ -131,7 +171,14 @@ World objects (pickables, harvestables) are **not** NetworkObjects. They use the
|
||||
owns a synced set of inactive ids + server-side authority (health, loot, drops) via RPC.
|
||||
Add new harvestable/pickable-like world state here, not as per-object NetworkObjects.
|
||||
`ItemData` cannot cross the wire — map items to ids through `ItemDatabase`
|
||||
(**Tools ▸ Ashwild ▸ Rebuild Item Database** after adding items).
|
||||
(**Tools ▸ Ashwild ▸ Rebuild Item Database** after adding items). `BuildRegistry` +
|
||||
`BuildableDatabase` mirror this for placed structures (which also accumulate to high counts).
|
||||
|
||||
This "no NetworkObjects" rule targets **high-count** world state (thousands of scatter objects,
|
||||
hundreds of builds) — making those NetworkObjects would flood the network. It is **not** absolute:
|
||||
a **transient, low-count** object that moves and needs smooth replication — the build ghost, one
|
||||
per player — is the case where a real **NetworkObject + client-authoritative NetworkTransform**
|
||||
is the better tool, and `BuildRegistry` spawns it as such. Pick by count and lifetime, not dogma.
|
||||
|
||||
### Shared interactables (cooking stations, future chests/benches)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user