It’s A Good Life Beta (Experiment)

It's A Good Life (Beta) is an experiment in building a complete hand-drawn-to-playable-game pipeline from scratch — pencil to SVG to Blender to Unity, entirely in one session.

The goal was to answer one question: how fast can an artist go from a drawing to something running in a browser? The answer turned out to be one day, with a working character, room, collision, camera follow, animation, music, and atmospheric audio — all sourced from hand-drawn art.

🎨 The Pipeline — Pencil to Browser

The full chain runs: hand-drawn art → SVG → Blender (automated) → GLB export → Unity → WebGL build.

  • SVG authoring: Shapes drawn in vector software with named groups. The parser reads group IDs to know what to build.
  • Blender automation: A single Python script (master_build.py) reads the SVGs and builds the entire 3D scene — room, chair, character billboard — without manual modelling.
  • GLB export: Three files land in an export/ folder: environment, props, sprites. Scale is 1 Blender unit = 1 Unity unit = 1 metre.
  • Unity import: GLTFast package handles GLB natively. Drag in, geometry and UVs transfer cleanly.
  • WebGL build: Published to Unity Play for browser embedding.

The key design rule: every stage is replaceable. Redraw the SVG, re-run the script, reimport the GLB — the game updates. No manual 3D work, no rebinding.

🎮 Unity — What Was Built
  • Character movement: WASD via Unity's New Input System. CharacterController handles collision. Y axis locked — no gravity, no jumping. Top-down diorama rules.
  • Camera follow: Fixed offset tracking in LateUpdate. Smooth damp eases the follow so it never snaps.
  • Room collision: Auto-generated Box Colliders per wall sourced from Blender face geometry data. Includes an invisible front barrier — the character can't walk out the open front of the diorama.
  • Sprite animation: 18 hand-drawn idle frames swap on a timer via SpriteAnimator.cs. One flat plane, one material slot, texture swap per frame. Paper Mario technique.
  • Scrolling pixel background: A Quad behind the room with a tiling Aseprite pixel art texture. UV offset increments each frame via BackgroundScroll.cs. Wrap Mode Repeat makes it seamless.
  • Atmospheric audio: Background music runs through an Audio Low Pass Filter. MusicMuffle.cs reads the character's Z position and maps it to the filter cutoff — front of room sounds muffled, back wall sounds clear. Like music heard through a wall.
  • Mood lighting: Single Spot light above the room centre. Warm yellow-orange, low intensity. Dim apartment feel.
📓 What I Learned (Gotchas Log)
  • Render Face → Both: Any interior mesh in Unity is invisible by default. Blender normals point inward — Unity culls back faces. Set Render Face to Both on every interior material.
  • New Input System vs Old: Input.GetAxis() throws an error if the New Input System package is active. Use Keyboard.current.wKey.isPressed instead.
  • Mesh Colliders on thin walls: CharacterController slides up face normals on thin wall meshes. Box Colliders per wall are more reliable for room interiors.
  • Play mode changes don't save: Any Inspector value changed during Play is discarded on Stop. Note values before stopping.
  • Inspector lock for bulk frame assignment: Lock the Inspector (padlock icon), select all frames in Project panel, drag onto the array header — Unity fills all slots at once.
  • Wrong scene in build: Build Profiles Scene List had the default empty SampleScene instead of the actual game scene. The build loaded a completely blank scene. Always verify the Scene List before building.
  • WebGL audio policy: Browsers block audio autoplay until the user interacts with the page. Music won't start until the player clicks.
  • AudioReverbZone properties locked by preset: ReverbPreset overrides manually set values at runtime. Switch to User preset and control Room and Reverb properties directly via script.
💻 Scripts Written
  • SpriteAnimator.cs — PNG frame swap animation on a mesh plane. Frames array + fps timer.
  • CameraFollow.cs — Fixed offset camera follow using SmoothDamp in LateUpdate.
  • CharacterMovement.cs — WASD movement via New Input System. Y locked to floor.
  • RoomWallColliders.cs — Auto-generates Box Colliders per wall from Blender face data. Includes invisible front barrier.
  • ScenePlacement.cs — Code-driven asset positioning on Start. Reproducible layout.
  • BackgroundScroll.cs — UV offset scroll on a Quad material. Mathf.Repeat for seamless loop.
  • MusicMuffle.cs — Low pass filter cutoff mapped to character Z via InverseLerp. Position-based atmospheric audio.
  • CameraSetup.cs — Forces camera clear flags to solid black on Awake. Prevents URP skybox bleed.
🔜 What's Next
  • Sprite alpha clipping — remove the black background from the character plane
  • Billboard behaviour — character sprite always faces the camera while moving
  • Walk animation state — swap to walk cycle frames when WASD is pressed
  • Wall and chair materials — PNG textures from the Blender pipeline
  • Auto-reimport editor script — detects GLB changes and reimports automatically
  • Expand the room — larger environment, additional props
Next
Next

Drumagery 🥁🖼️ v1