9.8 KiB
9.8 KiB
date, type, tags, permalink
| date | type | tags | permalink | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-06-03 | session |
|
gamevault/07-sessions/2026/2026-06-03-visual-upgrade-homebase |
Session 2026-06-03 — Art import + home-base visual upgrade (Synty/BefourStudios → URP)
Goal
The operator imported a large art/VFX asset bundle (commit e362aae, ~4,830 files) and asked to inventory it and use it to make the project look visually better, with more Synty packs coming later. Scope was set via a 4-question gate: render pass + curated home-base dressing, enemies/player stay primitives (no character meshes in these packs), VFX deferred, theme = clean orbital base. Locked in DR-010_Art_Import_URP_Conversion_Visual_Upgrade.
Inventory (what was actually imported)
- BefourStudios/Art (orbital-base modular kit — domes, batteries, crates, plants, modular blocks, lights, solar, storage), /SciFiEngineersRoom (interior), /BioHorrorSciFiEnvironment (organic/decay). ~560 prefabs, hundreds of FBX + PBR textures (
T_*_B/_N/_ORM). - GabrielAguiarProductions VFX = NOT in the repo — only 3 PDF docs committed; zero
.unitypackage/.vfx/prefabs. VFX deferred until imported. - No character meshes anywhere — packs are environment/props only.
- Pipeline mismatch: the art is HDRP-authored (
Shader Graphs/S_General, HDRP/Lit;_DISABLE_SSR_TRANSPARENT,RayTracingPrepass) while the project runs URP 17.4 + Entities Graphics → source materials render magenta under URP. Meshes + textures are fully usable; materials must be re-authored to stock URP/Lit (933532a4…, the same shader the project's working prototypes use → Entities-Graphics-compatible). Blank auto-generatedMI_*URP stubs exist but carry no textures.
Process
- Plan-gated (read-only): 3 Explore agents inventoried the packs + current visual/render setup; a Plan agent pressure-tested the execution sequence (corrected several of my assumptions by reading files). Operator approved.
- Implementation = sequential via MCP (single editor, domain-reload-ordered; NOT a parallel swarm): a reusable Editor converter, ghost-prefab mesh swaps (PrefabUtility round-trip), subscene dressing (open additive → place → save → re-bake), and a SampleScene render pass.
- Adversarial review workflow (3 lenses: code / netcode / conventions) over the diff. It earned its keep — caught 2 blockers + 1 major that the dark lighting masked in the screenshot. All fixed; minors triaged.
Done
Assets/_Project/Scripts/Editor/EnvArtTools.cs(new; Assembly-CSharp-Editor,#if UNITY_EDITOR) — reusable HDRP→URP material converter for future packs. Reads source texture refs across HDRP/Lit + ShaderGraph property names (_BaseColorMap/_BaseTexture→_BaseMap,_NormalMap/_NormalTexture→_BumpMap), type-guards every color/float/texture read (verifyShaderPropertyTypebeforeGetColor/GetFloat), low metallic (no reflection probe ⇒ high-metallic reads black), source-flag-gated emission, alpha-clip from source flags.ConvertCurated()menu item +RemapRenderersToEnv(go). GUID-preserving overwrite (refs survive re-runs). Outputs toAssets/_Project/Materials/Env/(20 materials).- Ghost prop mesh swaps —
Storage.prefab→SM_Storage_LOD0(scale 0.6),UpgradePickup.prefab→SM_Battery_LOD0+ emissiveM_Env_PickupGlow(scale 2.5). GhostAuthoring/LinkedEntityGroup/gameplay authoring preserved; only mesh+material+scale changed. - Two server spawners patched to preserve baked scale (
UpgradePickupSpawnSystem,SharedStorageSpawnSystem):LocalTransform.FromPosition()hard-sets Scale=1, which silently discarded the prefab scale — now they read the prefab's bakedLocalTransformand only override Position. - Gameplay subscene dressed —
EnvDecorroot of 13 collider-stripped, unpacked static props (dome backdrop, modular blocks, batteries/charger, crates, plants, light poles, solar panels) with URP materials; existingWall_North/East/Pillar_Centerre-skinned (colliders/positions kept) with tiledM_Env_Wall. No GhostAuthoring on scenery. - SampleScene render pass — cool key light @1.45–1.75; dark-space procedural skybox; flat dark ambient; exp fog @0.006 (keeps the z=26 dome visible);
Groundre-skinned to tiledM_Env_Floor;PostFX_DarkSciFiprofile populated (Bloom / ACES Tonemapping / ColorAdjustments / Vignette) and made the single active global volume (overlappingGlobalPostFXdisabled).
Validation
- EditMode 74/74 green (unchanged; the spawner edits compiled clean — note: EditMode test init timed out once on the unfocused editor, passed on retry with
init_timeout=180000). - Runtime (single in-editor client, 6.4.7): both worlds boot, 11 ghosts replicate server↔client; player input → prediction → replication works and the character is blocked by the east wall (static PhysicsWorld survived the dressing); ghost scales now apply (Storage 0.60, pickups 2.50, others 1.0). Console clean of code/Burst/material/bake errors (only "Server Tick Batching" warnings — the documented unfocused-editor symptom; decor adds zero server-sim load). Screenshots
Assets/Screenshots/result_clean_base.png(after) vsbaseline_editmode.png(before) confirm the jump. - Adversarial review (3 lenses): 2 blockers + 1 major, all fixed (below); remaining findings are minor/future-pack robustness, addressed or noted.
Diagnosis notes (for future me / future Synty packs)
- The art is HDRP, the project is URP. Source
M_*materials render magenta. Convert to stock URP/Lit viaEnvArtTools(do NOT switch the project to HDRP — it would break Entities Graphics). Meshes +_B/_N/_ORMtextures are reusable as-is. - A screenshot under dark lighting MASKS material bugs. The adversarial review caught a black-
_BaseColorblocker on ~16/20 materials:HasProperty("_BaseColorMultiply")was true (it's a float onS_General),GetColor()on a float returns (0,0,0) and logs a "doesn't have a color property" warning — the very warning I'd dismissed as cosmetic. Alwaysshader.GetPropertyType(idx)-guard beforeGetColor/GetFloat; the real tint is_AlbedoTint. Verify material values, not just the render. - Source emission needs the
_Emissive(0/1) flag gate.S_Generalcarries a non-zero default_EmissiveColoreven when emission is off → reading the color unconditionally made crates/dome/walls glow. Emit only when_Emissive>0.5AND the name marks a light fixture; flat color emission can't reproduce the source's emission mask anyway. VolumeProfile.Add<T>()does NOT persist the override as a sub-asset — on save thecomponentslist serializes 4{fileID:0}nulls (works in-session, gone after reload). MustAssetDatabase.AddObjectToAsset(component, profile)for each, thenSaveAssets. Verify on disk (non-null refs + N+1 MonoBehaviour blocks).LocalTransform.FromPosition()resets Scale to 1 — any ghost spawned via it ignores its prefab's authored scale (and Scale is a replicated[GhostField], so it's consistent-but-wrong, not a desync). Read the prefab's bakedLocalTransformand override only Position to keep authored scale.- High metallic + no reflection probe + dark skybox = near-black surfaces. Keep converted env metallic low (0.1–0.2); rely on albedo + direct light. (A baked reflection probe would let metallic read correctly later.)
- Metallic without reflections looked "too dark" before the tint bug was even found — two compounding causes (black albedo + high metallic); fixing both gave a bright, readable base.
- Editing a subscene via MCP:
manage_scene load … additiveopens the authoring scene (the baked-entity view it was showing goes away — empty game view is expected), edit +SaveScene, thenclose_sceneso the SubScene re-bakes from the saved file on Play. Verify placement viaexecute_codeenumerating the scene roots, not the game view. - HUD-free beauty shot: a positioned
game_viewcapture (view_position/view_rotation) uses direct camera rendering, which excludes Screen-Space-Overlay UI — so the gameplay death overlay doesn't bleed into the render. (scene_viewrejects positioned capture.) execute_codeis a method body (no usings; fully-qualify). Reusable converter logic belongs in a committed Editor script, not repeatedexecute_codeblobs — the operator is importing more packs.
Open / deferred
- VFX — import the GabrielAguiar
.unitypackages, then wire the Shuriken packs (projectiles/explosions/shields/auras) into the existing clientParticleSystempool; the VFX Graph packs (hits/beams) need separate URP setup. - Characters — player/enemies are still primitives; swap for real models when a character/Synty pack arrives (the prefab+material pattern generalizes).
- Decor LODs bake into both worlds — the 13 props' full LOD hierarchies are in the shared subscene, so the server carries renderable+
MeshLODGroupentities for nothing. For more decor, move pure cosmetics to a client-only/cosmetic subscene or flatten to LOD0. - Higher material fidelity — current converter uses uniform metallic/smoothness (ORM channels don't map to URP); a per-channel ORM→URP repack (or a small ORM ShaderGraph) + a baked reflection probe would deepen the look.
- More dressing — mine
S_OrbitalBase.unityfor a fuller layout once the pipeline is proven; the BioHorror pack fits future "corrupted" arena zones (mixed-theme option from the scope gate).
Next
Either import + wire the VFX (biggest feel win, needs the operator to import the packs) or deepen the environment (more orbital-base dressing + a reflection probe + ORM fidelity). The reusable EnvArtTools converter + the duplicate-and-reskin prefab pattern are the foundation for every future Synty pack.