Asset Dump

This commit is contained in:
2026-06-03 13:46:13 -07:00
parent e362aaeb43
commit 9091388bc2
20821 changed files with 26544125 additions and 58 deletions
@@ -0,0 +1,55 @@
---
id: DR-010
title: Art import + home-base visual upgrade — HDRP→URP material conversion pipeline for Synty/BefourStudios packs
status: accepted
date: 2026-06-03
tags:
- decision
- art
- urp
- entities-graphics
- materials
- presentation
- home-base
- tooling
permalink: gamevault/07-sessions/decisions/dr-010-art-import-urp-conversion-visual-upgrade
---
# DR-010 — Art import + home-base visual upgrade (HDRP→URP conversion pipeline)
## Context
The operator imported a large art/VFX asset bundle (commit `e362aae`, ~4,830 files: BefourStudios orbital-base + sci-fi-interior + bio-horror kits, plus GabrielAguiar VFX) and asked to inventory it and **make the project look better**, with more Synty packs coming. The project ([[Identity]] sci-fi frontier colony, see [[DR-009_GameFeel_Identity_FirstBlood]]) was a primitive-shape debug scene under a cool URP post-FX look. Inventory surfaced three constraints that shaped everything:
1. **The art is HDRP-authored; the project is URP 17.4 + Entities Graphics.** BefourStudios props reference `Shader Graphs/S_General` and HDRP/Lit (`_DISABLE_SSR_TRANSPARENT`, `RayTracingPrepass`, `_BaseColorMultiply`/`_AlbedoTint`/`_Emissive` props) → they render **magenta** under URP. The **meshes + PBR textures** (`T_*_B/_N/_ORM`) are fully usable; the auto-generated `MI_*` URP material stubs are blank.
2. **The VFX packs were never extracted** — only 3 PDF docs are committed (no `.unitypackage`/`.vfx`/prefabs).
3. **No character meshes** exist in any pack — they are environment/props only.
Operator scope gate (4 questions): **render pass + curated home-base dressing**; enemies/player stay primitives; **defer VFX**; theme = **clean orbital base**.
## Decision
1. **Convert HDRP art to stock URP/Lit; do NOT switch the project to HDRP.** Switching pipelines would break the Entities Graphics setup the whole game depends on. Instead a **reusable Editor tool** (`Assets/_Project/Scripts/Editor/EnvArtTools.cs`, Assembly-CSharp-Editor, `#if UNITY_EDITOR`) reads each source material's texture refs across HDRP/Lit + ShaderGraph property names and builds a **stock URP/Lit** material (shader `933532a4…`, the same one the project's working prototypes use → DOTS-instancing/Entities-Graphics compatible) in `Assets/_Project/Materials/Env/`. It is **GUID-preserving on overwrite** (scene/prefab refs survive re-runs) and built for the incoming Synty packs (edit `CuratedPrefabNames` or call the public statics). Key correctness rules baked in after the adversarial review: **type-guard every `GetColor`/`GetFloat`/`GetTexture`** (verify `shader.GetPropertyType(idx)` first — the real tint is `_AlbedoTint`, NOT the float `_BaseColorMultiply` which `GetColor()` reads as black); **low metallic** (0.10.2 — high metallic + no reflection probe + dark skybox = near-black); **emission gated on the source `_Emissive` flag AND a light-fixture name** (the shader graph carries a non-zero default `_EmissiveColor` even when off); alpha-clip read from source flags.
2. **Ghost props swap mesh+material only; spawners preserve baked scale.** `Storage.prefab``SM_Storage_LOD0` (0.6), `UpgradePickup.prefab``SM_Battery_LOD0`+emissive `M_Env_PickupGlow` (2.5), preserving `GhostAuthoringComponent`/`LinkedEntityGroupAuthoring`/gameplay authoring (single-GameObject, no added children — interpolated replication unchanged). Because `LocalTransform.FromPosition()` hard-sets Scale=1, **the two server spawners (`UpgradePickupSpawnSystem`, `SharedStorageSpawnSystem`) were patched** to read the prefab's baked `LocalTransform` and override only Position — otherwise authored ghost scale is silently discarded (Scale is a replicated `[GhostField]`, so it was consistent-but-wrong, not a desync). This is the one gameplay-code change, and it's a latent-bug fix that future ghost-prefab sizing depends on.
3. **Static decor lives in the gameplay subscene; cosmetics-only.** An `EnvDecor` root of 13 **collider-stripped, unpacked** static props (dome backdrop, modular blocks, batteries/charger, crates, plants, light poles, solar panels) with converted URP materials, plus re-skinned existing walls/pillar (colliders + positions kept — predicted-physics collision intact). **No GhostAuthoring on scenery** (stays non-replicated, deterministic, present in both worlds). Decor renders via Entities Graphics from the subscene bake; the SampleScene `Ground`/skybox/fog render via classic URP — both coexist under the one camera.
4. **Render pass on SampleScene + the project-owned post-FX profile.** Cool key light; dark-space procedural skybox; flat dark ambient; exp fog @0.006 (keeps the z=26 dome backdrop visible); `Ground` re-skinned to a tiled sci-fi floor. The **`PostFX_DarkSciFi` volume profile is populated** (Bloom / **ACES** Tonemapping / ColorAdjustments / Vignette) and made the single active global volume (overlapping `GlobalPostFX` disabled). Effects are persisted as **sub-assets via `AssetDatabase.AddObjectToAsset`**`VolumeProfile.Add<T>()` alone serializes null component refs that vanish on reload.
## Consequences
- **Validated at runtime (6.4.7, single in-editor client):** both worlds boot, 11 ghosts replicate, player input→prediction→replication works and the character is still **blocked by the static walls**; ghost scales now apply (Storage 0.60, pickups 2.50); console clean of code/Burst/material/bake errors (only "Server Tick Batching" — the documented unfocused-editor symptom; decor adds zero server-sim load). **EditMode 74/74.** Before/after screenshots confirm the jump from a primitive debug scene to a textured, lit orbital base under a dome.
- **The adversarial review was decisive.** A "looks good" dark-lit screenshot **masked two blockers** (black-`_BaseColor` on ~16/20 materials; post-FX that never persisted to disk) + one major (inert ghost scale). All fixed. The lesson: under stylized dark lighting, **verify material/asset *values*, not just the render.**
- **Reusable for every future pack** — `EnvArtTools` + the duplicate-and-reskin prefab pattern + the spawner-preserves-scale fix generalize. The remaining cost ceilings (uniform metallic/smoothness vs ORM; decor LODs baking into both worlds) are documented for later.
- **No vendor assets modified, no shared-material bleed** — converted materials are new assets in `Materials/Env/`; the project's `M_Dummy` and all originals untouched; the two ghost prefabs changed only mesh/material/scale.
## Open / deferred
- **VFX** — packs aren't in the repo; once imported, wire the Shuriken ones into the existing client `ParticleSystem` pool ([[DR-009_GameFeel_Identity_FirstBlood]]'s presentation layer); VFX-Graph hits/beams need separate URP setup.
- **Characters** — player/enemies stay primitives (no character meshes in these packs).
- **Server LOD bloat** — pure decor's full LOD hierarchies bake into both worlds; move to a client-only/cosmetic subscene or flatten to LOD0 as decor grows.
- **Material fidelity** — uniform metallic/smoothness (ORM channels don't map to URP); a per-channel ORM repack + a baked reflection probe would deepen the look.
- **Mixed-theme arena** — the BioHorror pack fits future "corrupted edge" zones (a scope-gate option not taken this pass).
Expresses [[Identity]]; builds on [[DR-008_M5_HomeBase_BaseLayer_Storage]] (BaseAnchor, duplicate-an-existing-ghost) and [[DR-009_GameFeel_Identity_FirstBlood]] (URP post-FX look, client-only presentation). Session: [[2026-06-03_Visual_Upgrade_HomeBase]].
@@ -0,0 +1,49 @@
---
id: DR-011
title: Grounded Synty sci-fi world (SampleScene/classic-URP) + GabrielAguiar Shuriken VFX integration
status: accepted
date: 2026-06-03
tags:
- decision
- art
- synty
- urp
- vfx
- presentation
- environment
- world
permalink: gamevault/07-sessions/decisions/dr-011-synty-world-vfx-integration
---
# DR-011 — Grounded Synty world + GabrielAguiar VFX
## Context
After [[DR-010_Art_Import_URP_Conversion_Visual_Upgrade]] (BefourStudios HDRP→URP base on a small grey plane), the operator imported the GabrielAguiar VFX (now extracted) and a batch of **Synty POLYGON** packs and asked to: implement the VFX, **stop the world looking like a floating plane** (terrain/grounded, deepen the environment), inventory + use the Synty packs, and keep everything **cohesive**. Inventory found: GA is **94% Shuriken** (pool-friendly, URP-ok); Synty is **URP-native** (`Synty/Generic_Basic`, no conversion) with `SciFiCity+SciFiSpace+Mech` forming a cohesive flat-shaded sci-fi set (buildings, walls, 14 planets, asteroids, hangar floors). The semi-realistic BefourStudios base would clash with stylized Synty. Operator forks: **go full Synty** (retire BefourStudios) and **keep primitives** for player/enemies (no DOTS skeletal animation → static rigged meshes would slide as T-poses).
## Decision
1. **Build the grounded world as COSMETIC classic-URP GameObjects in SampleScene — not the DOTS subscene.** Synty materials use a custom shader (`Synty/Generic_Basic`); as plain SampleScene GameObjects under the client camera they render via classic URP with zero risk, and we never have to verify the Synty shader's Entities-Graphics DOTS-instancing. Only the gameplay subscene needs Entities Graphics + the baked PhysicsWorld. A `SyntyWorld` root holds ~60 objects: a large ground plane, a paved tech plaza over the play area, a 16-building skyline ring + perimeter walls (depth), boundary barriers aligned to the collision walls, props, a planet + asteroid backdrop, a space skybox, brighter flat ambient + light fog. **"Grounded" was achieved by surrounding the arena (skyline + planet horizon + fog) rather than by a bigger plane.**
2. **Retire BefourStudios for cohesion.** Delete the subscene `EnvDecor` (dome/props); **disable** the `Wall_North`/`Wall_East`/`Pillar_Center` MeshRenderers but **keep their BoxColliders** — a disabled renderer still bakes its static `PhysicsCollider` (gameplay collision intact) and no RenderMesh, so the boundary is invisible while the cosmetic Synty barriers + skyline define the space. The old grey `Ground` renderer is disabled (its classic MeshCollider is harmless — not in the DOTS world).
3. **GabrielAguiar Shuriken VFX via a `VFXConfig` bridge + `CombatFeedbackSystem`.** `VFXConfig` (a `ProjectM.Client` MonoBehaviour with a static `Instance` + 5 prefab slots, in the bootstrap scene — mirrors `PrototypeCameraRig`) hands authored prefabs to the client presentation system. `CombatFeedbackSystem.Burst()` instantiates the authored prefab at each hook (muzzle / hit / enemy-death / player-death), falling back to the existing procedural ParticleSystem when a slot is null. `UpdateProjectileTrails()` makes a trail GameObject follow each projectile ghost (query `WithAll<Projectile>()` each presentation frame; dict-by-`Entity` spawn/reposition/prune). Still pure client presentation — observes replicated state, never mutates the sim.
4. **Every spawned cosmetic VFX is stripped to particles (`StripCosmetic`).** GA "projectile" prefabs are self-moving demos (non-kinematic Rigidbody + collider + `ProjectileMoveScript` + secondary muzzle/hit spawns). On instantiate we destroy any `Rigidbody`/`Collider` and disable any `Projectile`/`Move`-named MonoBehaviour (before its `Start` runs), so only the ParticleSystems remain and our per-frame reposition is authoritative. VFX lifetime is derived from the prefab's longest ParticleSystem (clamped 16 s); a `MaxActiveVfx` cap bounds GC churn under swarms.
5. **Player/enemies stay primitives.** No character-mesh swap this pass — Entities Graphics has no easy skeletal animation, so a static rigged Synty character would slide as a T-pose (worse than a clean glowing shape). The world + VFX carry the upgrade; revisit characters when DOTS animation is added.
## Consequences
- **Validated at runtime (6.4.7, single in-editor client):** both worlds boot, 11 ghosts replicate, the dome correctly gone after re-bake, **player collision with the invisible subscene walls intact**, the **blue hit VFX fires** on husk contact with no console errors, and the world reads as a cohesive grounded Synty sci-fi colony (planet horizon + city skyline + plaza, no floating edge). **EditMode 74/74.**
- **Adversarial review caught 1 blocker** (the demo-projectile-as-trail physics rig) + perf notes — all fixed (`StripCosmetic`, duration-based TTL, VFX cap, single active Volume confirmed). The scene/netcode isolation (cosmetic classic-PhysX colliders vs the baked DOTS PhysicsWorld) was verified end-to-end: **the cosmetic world cannot affect gameplay/netcode/determinism.**
- **Reusable patterns:** Synty-in-SampleScene (classic URP, no conversion), the `VFXConfig` bridge + `Burst`/`SpawnVfx`/`StripCosmetic` + projectile-follow trail, and disabled-renderer-kept-collider for swapping a subscene's visual style. The two server spawners' baked-scale fix from DR-010 carries the rescaled ghost props.
## Open / deferred
- Confirm fire-driven VFX (muzzle / projectile trail / enemy-death) visually with a focused editor / real client (one-shot Fire drops under the unfocused editor; same verified `SpawnVfx` path as the confirmed hit VFX).
- Ghost-prop cohesion gap: Storage/UpgradePickup ghosts still use BefourStudios meshes (render via EG; a Synty mesh there needs the Synty shader's DOTS-instancing verified). Prune the now-orphaned `Materials/Env/` decoratives.
- Characters (player/enemies) still primitives — pending DOTS skeletal animation.
- Perf budgeting (top-down Bloom + ~60 Synty objects + planet) and VFX-Graph hit/beam setup if wanted; mixed-theme corrupted zones (BioHorror) deferred.
Expresses [[Identity]]; supersedes the BefourStudios environment of [[DR-010_Art_Import_URP_Conversion_Visual_Upgrade]] (its converter/ghost-scale fixes still stand); builds on [[DR-009_GameFeel_Identity_FirstBlood]] (client-only presentation, `CombatFeedbackSystem`). Session: [[2026-06-03_Synty_World_And_VFX]].
@@ -0,0 +1,61 @@
---
id: DR-012
title: Mouse-cursor aim + gamepad twin-stick controls (client-derived aim, scheme-gated assist)
status: accepted
date: 2026-06-03
tags:
- decision
- input
- controls
- netcode
- aiming
- presentation
- gamepad
permalink: gamevault/07-sessions/decisions/dr-012-aim-controls-cursor-gamepad
---
# DR-012 — Mouse-cursor aim + gamepad twin-stick controls
## Context
Controls felt janky: on mouse+keyboard the character could only fire along its **movement** direction — there was no cursor aim. Root cause: `PlayerInput.Aim` was bound **only** to `<Gamepad>/rightStick` in `Project M Input.inputactions`, and `controlSchemes` was empty, so on KBM `Aim` was always zero and `PlayerAimSystem` fell back to the movement heading. The operator asked to: show a cursor for aiming on KBM, make the character **face the cursor** (fire while standing still), **preserve gamepad** support, and research how V Rising / similar handle KBM+gamepad.
Research (V Rising primary; Hades/Halls of Torment/Diablo 4/Brotato) confirmed: KBM = continuous face-cursor decoupled from movement (strafe while aiming) with a visible cursor; gamepad = right-stick 360° aim with a world reticle; auto-switch on last-used device; **aim-assist is gamepad-only** for multiplayer fairness. Operator forks chosen: **per-scheme native** reticle (KBM crosshair + gamepad world ring) and **precise mouse / gamepad-only auto-aim**.
Key enabling insight: `PlayerInput.Aim` is already a replicated `[GhostField]` direction consumed by predicted `PlayerAimSystem` (facing) + `AbilityFireSystem` (shot dir), and `PlayerControlSystem` already drives movement from `Move` (decoupled from facing). So the fix is almost entirely **client input + presentation** — strafe-while-aiming comes free the moment `Aim` reflects the cursor.
## Decision
1. **Mouse aim is computed client-side and streamed via the EXISTING `PlayerInput.Aim` — no new ghost/netcode surface.** In `PlayerInputGatherSystem` (managed `SystemBase`, `GhostInputSystemGroup`, once per frame) the KBM path reads `Mouse.current.position`, projects `Camera.main.ScreenPointToRay` onto the player's movement plane via the pure helper `AimMath.PlanarAimFromRay(...)`, and writes the player→cursor direction as `Aim`. The heavy managed math stays client-only; only the resulting normalized direction (+ a scheme byte) crosses the wire, so predicted/server systems are structurally unchanged and deterministic. `AimMath` is Burst-safe and **unit-tested** (`AimMathTests`, 7 cases: down/diagonal rays, parallel/away/over-player fallbacks, plane-Y).
2. **Active scheme = last-meaningful-actuation-wins, replicated as one `byte`.** Gather detects KBM vs gamepad each frame (stick/trigger/button past a 0.04 lengthsq deadzone vs mouse-delta >0.5px / click / movement key; `InputDevice.lastUpdateTime` breaks ties; holds last when idle) and writes `PlayerInput.Scheme` (`InputSchemeId.KeyboardMouse=0 / Gamepad=1`). It is a **`byte` GhostField, not an enum** — cross-assembly enum-in-Burst tripped the type-hash ICE before (cf. `ProjectileClassificationSystem`), and `Scheme` is compared inside the Burst-compiled `AbilityFireSystem`.
3. **Auto-target assist is gated to gamepad (precise mouse).** `AbilityFireSystem` (server) applies the 12u/35° `AutoTarget` cone only when `applied.InternalInput.Scheme == InputSchemeId.Gamepad` (read from the same `GetDataAtTick` lookup used for the fire-count key, so it matches the exact fire tick). Mouse shots fly exactly to the cursor; gamepad keeps the assist. Bonus: mouse now predicts == server (no assist on either) → fewer reconcile snaps.
4. **Per-scheme native presentation in a client `PresentationSystemGroup` SystemBase (`AimReticleSystem`) that OBSERVES, never mutates.** KBM → a procedural crosshair `Texture2D` via `Cursor.SetCursor` replaces the OS arrow (cursor visible); gamepad → OS cursor hidden + a flat world-space ring (primitive quad, `Sprites/Default`, procedural ring texture) placed `ReticleDistance` ahead of the local player along the replicated `PlayerFacing`. Asset-free (mirrors `HudSystem`/`CombatFeedbackSystem`); cursor is re-applied only on a scheme change and **restored to OS default on `OnDestroy`**. The active scheme is handed over by a static bridge `AimPresentation.Scheme` (mirrors `PrototypeCameraRig`/`VFXConfig`), which **resets on play-enter** via `[RuntimeInitializeOnLoadMethod(SubsystemRegistration)]` (statics survive fast-enter-playmode domain reloads → a stale gamepad value would flash wrong presentation for the first frames).
5. **Gamepad neutral-stick keeps the existing face-movement fallback.** When the right stick is resting, `Aim` is zeroed and `PlayerAimSystem` falls back to the movement heading (controller-first behaviour, unchanged). The `.inputactions` asset was **not edited** (mouse aim bypasses the action; Fire/Move already cover both devices) — no wrapper regeneration.
## Consequences
- **Validated (6.4.7, single in-editor client):** compile/Burst/source-gen clean, **0 new warnings**, **EditMode 81/81**. Runtime: both worlds boot, player spawns, **no exceptions**; the `Scheme` byte replicates to the server (read back `Scheme=1`), injected `Aim=(1,0)` drives server `PlayerFacing=(1,0)`, and under a forced gamepad scheme the world reticle activates, lies flat (`rotX=90`), positions 4u ahead of the player, has its material, and the hardware cursor hides.
- **Adversarial multi-agent review (5 dimensions, verified):** 5 confirmed / 5 correctly rejected. Fixed: the `AimPresentation` static-reset (the major), a `Shader.Find` fallback+guard, and `DebugInputInjectionSystem` now syncs `AimPresentation.Scheme`. Declined (verified correct): `mainTexture` vs `_MainTex` (canonical API, renders fine).
- **Reusable patterns:** client-derived input on an existing `[GhostField]` direction (no new netcode surface); a replicated scheme byte to gate server-only assist; `AimMath` as a pure unit-tested projection; the reset-static-presentation-bridge idiom.
## Refinement — world-space cursor (follow-up, 2026-06-03)
Operator feedback after the first pass: make KBM aiming feel more natural / world-space. A research workflow (V Rising action-mode cursor-hide; Last Epoch / PoE2 / Diablo; TopDown Engine `ReplaceMousePointer`; dual-stick feel — gamedeveloper.com) confirmed the perspective-mismatch artifact (a flat screen crosshair sits visually above the angled ground point it targets) and recommended reticle-only. Changes (these **supersede decision #4's KBM screen crosshair**):
- **KBM uses the world-space ground ring at the cursor's ground-projection point** (not a screen crosshair); the OS cursor is hidden while aiming. The point is **re-raycast inside `AimReticleSystem`** (PresentationSystemGroup, after the follow-cam's LateUpdate move) — NOT latched from the gather (`GhostInputSystemGroup`, before the move), else the ring drifts one frame behind under the moving camera. New pure `AimMath.TryGroundHit` returns the world point; the last valid point is held on a miss. Cursor restored on focus-loss/destroy (`Application.isFocused`-gated). Both schemes now use one grounded ring (KBM at the cursor point, gamepad a fixed distance ahead) — consistent UX.
- **Radial dead-zone** (`PlanarAimFromRay` `deadZoneRadius`, 0.6u) holds facing when the cursor is on/near the character.
- **Camera look-ahead** (`PrototypeCameraRig.AimLeadDistance`, tunable, default 2.5u, 0 = off): leads the framed point toward the replicated `PlayerFacing` — driven off facing, not the cursor projection, so there is no feedback loop with the camera-dependent ground raycast. `PrototypeCameraTargetSystem` publishes `TargetFacing`.
- **Skipped** (with reasons): constant-screen-size scaling (fixed-distance cam), aim line (redundant with the ring), KBM enemy-magnetism (would undermine the intentional gamepad-only assist).
- Validated: EditMode **86/86**, console clean; runtime (focused) KBM ring active at the cursor ground point, OS cursor hidden, `TargetFacing` published, no exceptions.
## Open / deferred
- The **real mouse-cursor path + live device auto-switch** need a **focused** Game view — the unfocused editor can't inject mouse position / device actuation (validated the replication, math, gate, and reticle headlessly via `DebugInputInjectionSystem` + forced scheme). Operator focused click-test pending.
- Auto-target priority/feel tuning; optional controller soft-target reticle snap (V Rising / Diablo-style) deferred.
- Future: rebindable controls, multiple ability slots, and `controlSchemes` population if the Input System's built-in scheme switching is later preferred over the manual detector.
See [[2026-06-03_Aim_Controls_Cursor_Gamepad]]. Builds on [[DR-007_M5b_Character_Controller_Package]] (movement decoupled from facing) and [[DR-003_M2_Combat_Netcode_Architecture]] (input/command pipeline, `AutoTarget`).