In an inner wall/ceiling corner the body's facing flipped ~9 deg every
frame. Recorded frame data showed the wall/ceiling classification flipping
160 times: _wallNormal.y swung the full range (0.0 wall <-> -0.966 ceiling)
each frame, far past the hysteresis band, so the Schmitt trigger could not
hold it.
Root cause: _wallNormal had two competing per-frame sources.
- The contact-normal blend (Update) mixes ceiling and wall contacts in the
corner into ~(0,-0.97,-0.26), classified as ceiling.
- ProbeWall raycasts along -_wallNormal, which tilts toward the wall, so the
ray clips the wall and returns (0,0,-1), classified as wall.
Wall and ceiling drive different rotation targets (snap to face-wall vs.
face movement direction), producing the per-frame twitch.
Fix:
- The contact blend no longer overwrites _wallNormal during an active climb
(it only seeds the initial grab); the probes own the normal while climbing.
- Surface-aware probing: on a ceiling, probe straight up (ProbeCeiling)
instead of along -_wallNormal, so the angled ray can no longer clip the
wall and demote us. Stay latched on the ceiling until it is genuinely gone
overhead, then fall back to the wall probe.
Also retains the ceiling-class hysteresis (Schmitt trigger on the normal's
downward tilt) from the prior attempt as added stability.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each PlayerPose now carries its own collider center Y, radius and height,
eased and routed to the CharacterController via a SetCapsule single-writer.
This lets crawl poses (Ball/Star) shrink the capsule to fit under furniture.
The ceiling Y offset is removed; poses without authored sizes fall back to
the base capsule, so existing poses keep their collision.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace unreliable raycast parity on open-shell meshes with editor-baked
voxel grids. ConcealmentVolume bakes an inside-mask per object using the
union of a generalized-winding-number test (solid material, robust to open
shells) and an exterior flood-fill (enclosed cavities). ConcealmentMeter
now prefers baked volumes via an O(1) world-space lookup through a registry,
falling back to the old concave parity only for un-baked colliders.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a free-fly camera as the next entry in the Tab mode cycle
(Player Control -> Paint -> Free Cam):
- FreeCamController: dedicated CinemachineCamera plus a CharacterController
mirroring the player capsule (radius 0.1, height 1.3, slope 59, step 0.15)
so the free camera collides with walls/ceiling/floor exactly like the
player. WASD/Q-E (and Space/Ctrl) fly relative to view; mouse looks.
- FreeCamMode: plain-C# GameMode mirroring PaintMode, with an Exit() that
restores camera priority and re-enables player control + camera input.
- GameModeManager: register freeCam in the Tab cycle (gated like player).
- Scene: FreeCamera object wired, Main Camera custom blends (0.4s) for the
vcam priority hand-off.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add cameraTargetYOffset to PlayerPose so each pose can offset the
Cinemachine ThirdPersonCamera follow/look target independently of the
body mesh. PlayerCharacterController gains a cameraTarget reference
(auto-resolved via the "CameraTarget" child, base position captured in
Awake) and a single-writer SetCameraTargetLocalYOffset. PlayerPoseController
eases the per-pose camera offset and composes it with the shared ceiling
offset, so the camera target follows the ceiling lift in lockstep with the
mesh. Wire cameraTarget explicitly in SampleScene.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Import Barking Dog's free URP-ready interior asset (~41 MB, 155 assets:
meshes, textures, materials, prefabs) as the small interior map, and
populate SampleScene with its geometry.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- PlayerPoseController: add applyFootIK toggle (default off) and apply it
to each pose playable so straight-knee idles render straight; Mecanim
foot IK was bending the knees to plant the feet (162° instead of 180°).
- Add Pose_Ball / Paintman-Ball animation and reorder the pose list.
- Move StraightenKneesTool editor utility under Assets/Unused/Editor.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Import Mixamo humanoid Walking + Running FBX, switch rig type to Humanoid
- Wire walkClip/runClip with per-clip speeds on Pose_Idle (walk 1.4, run 1.5)
- Add per-animation speed sliders (Range 0.1-3, default 1) to PlayerPose SO,
applied per frame in PlayerPoseController for live tuning
- Reorganize pose assets: replace Pose_TPose with Pose_Hold, prune legacy
Paintman-Run/-TPose .anim and paintman_UV.FBX
- Ignore UMotion plugin data/editor folders
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ConcealmentMeter: standalone component measuring the percentage of the
character volume embedded inside environment geometry (bake -> voxelize via
column ray-stabbing parity -> classify interior voxels against box/sphere/
capsule/convex colliders and terrain). Always-on, throttled, gizmo debug.
- SkinnedColliderBaker: sole per-frame collider bake owner for skinned rigs.
MeshPainter now delegates baking and only borrows BakedMesh for the GPU
raster and cache refresh, so the collider stays fresh outside paint mode.
- Move pose assets to Assets/Poses, retire unused Insect scripts to
Assets/Unused, restore Paintman.controller; mode scripts and scene updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New PlayerPose ScriptableObject (AnimationClip + ceiling Y-offset) and
PlayerPoseController that drives poses via a PlayableGraph, overriding the
Animator controller. Poses are held continuously (idle, moving, on wall/
ceiling) so cycle and sprint changes show immediately. Sprinting in any
state resets to pose 0. Non-keyed bones fall back to a captured rest pose
so empty/partial clips apply fully. Ceiling Y-offset is folded into the
controller's single mesh-offset writer.
PlayerCharacterController gains IsIdle / IsSprinting / IsOnCeiling /
AnimatorOverridden accessors and SetPoseLocalYOffset; SetAnimatorRunning is
guarded while a pose owns the Animator. Removed obsolete Paintman.controller.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PlayerCharacterController:
- Wall lean now moves only the visual model + its paint collider (auto-resolved
mesh root parenting both renderer and bones), not the CharacterController
capsule, so the mesh can sink into the wall (wallMaxInset) as well as lean out
(wallMaxOffset); capsule stays flush.
- Lean eases back to the authored pose when leaving the wall instead of snapping.
- Sprint multiplier now also applies while wall/ceiling climbing.
- Separate wallMantleSpeedMultiplier for pulling up over the top edge,
independent of the climb speed.
Assets:
- Re-exported paintman_UV.FBX and added Paintman.blend: rescaled armature to
mesh, merged seam duplicate vertices, fresh automatic weights, inner-thigh
weight fix (no webbing on leg spread).
- Updated anims, animator controller, font SDF and scene.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add player position/rotation/wall-climb persistence and camera
orbit (yaw/pitch/radius) persistence, auto-saved on quit/play-stop
and auto-loaded on start. Also includes the wall-climb fixes
(directional top-out, base detach on push-away).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the CPU island-mask dilation guard on the GPU backend with a
coverage pass rendered through the same brush rasterizer, so sub-pixel
rim texels that the GPU brush can never reach fall into the gutter and
stay paintable (no more frozen loaded pixels at island edges).
Also includes user content: additional brush masks (dirt) with an
expanded mask selector in the HUD prefab, and CharacterController /
wall-climb inspector tuning.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add mask selector with previews to the brush card (data-driven from
painter.brushMasks); persist activeBrushIndex with HUD layout.
- Fix alpha/coverage artifacts when overpainting after load or backend
switch: derive the dilation source marker from a deterministic UV island
mask instead of resetting it to "unpainted" on every seed.
- Import the two final brush mask textures (Brushes/).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- PlayerCharacterController: latch the wall-strafe sign once at strafe
start instead of re-deriving it from the camera every frame, which
flipped at the 90-degree point while circling a cylinder and caused a
back-and-forth lock. Flat walls stay bit-identical; reset on enter/exit.
- MeshPainter.Pick: dispatch terrain hits to a splat-layer blend (full
PBR channels), terrain trees / grass / sky to rendered screen-color,
keeping texel-accurate picks for the paint mesh and foreign materials.
- Includes Unity auto-reserialization of SampleScene and three Supercyan
pack assets (URP material upgrades, skybox/lighting) from the import.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reset the pipette toggle after a successful pick so each pick is a
one-shot action (HUD toggle follows via the Picked sync). Split the
wall-climb pose drag so the lean-out offset stays on LMB while body
rotation moves to RMB, letting both be held independently. Also pulls in
the terrain physics module and the user's scene setup for the terrain
test area.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The pipette now raycasts the nearest collider of any object, not just the
paint mesh. On a foreign hit it reads all channels texel-accurately from the
object's material maps (BaseMap/MetallicGloss/Occlusion/Emission) combined
with the material scalars per URP/Lit conventions, falling back to scalar
properties where a map is missing or the collider yields no UV. Includes
scene test props and materials for verifying foreign-object picking.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Spray brush mode: bakes a procedural scattered-dot mask per stamp (random
position, size, alpha within the brush disc) and paints it through the
existing single-stamp pipeline; dot centers clamped to (0.5 - dotR) so the
spray footprint matches the solid brush radius.
Paint interval: float on MeshPainter; 0 keeps the continuous interpolated
stroke, >0 emits a single timed dab every x.xx seconds.
Color picker alpha: horizontal alpha bar on both HSV pickers, runtime-built
in Rebind (no prefab re-bake), passed through to brushColor.a / emissionColor.a.
Metallic/smoothness + occlusion paint opacity: new opacity fields applied in
both CPU and GPU backends (GPU MSO draw split into MS and occlusion sub-stamps
for independent opacity), with cloned alpha sliders wired into the HUD.
Also includes the prefab layout tweaks and scene adjustments.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Assign the baked PaintHudPanel prefab to the scene PaintHud, lower the
emission intensity and brush size defaults, and adjust camera and hand
rest positions.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the new Player (Variant 2, Hand) with HandIK and the InsectController,
boot directly into Insect mode, and apply Unity-managed serialization updates
to the physics, renderer, and post-process settings assets.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the HandIK component to Player/WhiteHand with handRoot wired to the
Hand node so the finger IK system is active in the scene.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Make wall-climb controls wall-relative: W approaches/climbs up,
S moves away and detaches, A/D strafe along the wall
- Add slow approach speed for moving toward/away from the wall
- Remove wall-climb activation time (activate on contact)
- Add mantle/top-out over the top edge so the player pulls onto the
surface instead of dropping and re-grabbing (fixes edge flicker)
- Add re-grab cooldown after top-out
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce an extensible game mode system toggled with Tab:
- Player Control: WASD movement with always-on mouse camera orbit
- Paint: player frozen, left-click paints, right-click holds to orbit
Add GameMode base class, GameModeManager, and the two concrete modes.
Refactor controlled scripts to expose clean state flags instead of
handling input themselves: ThirdPersonOrbitInput.LookMode,
PlayerCharacterController.ControlEnabled, MeshPainter.PaintingEnabled.
Also fix camera zoom: remove the obsolete /120 wheel normalization so
one scroll notch maps to one zoomSpeed step under the new Input System.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Install Cinemachine 3.1.7 and set up an orbital third-person camera rig
(CinemachineBrain, OrbitalFollow, RotationComposer, Deoccluder).
- Add ThirdPersonOrbitInput: mouse-driven orbit and wheel zoom with a Tab
toggle that unlocks the cursor and pauses rotation.
- Fix MeshPainter so the paint ray skips the player's CharacterController
capsule (and any other collider) and always targets the mesh collider,
so painting works from every camera angle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add PlayerCharacterController script: CharacterController-based
movement (camera-relative WASD), jump, gravity, rotate-toward-movement
and slope sliding so the player slides off surfaces/edges steeper than
the slope limit instead of balancing on them.
- Update SampleScene: add Player (with CharacterController), ground plane
and obstacle cubes; parent the paintable paintman_UV under the Player.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Unity 6000.3 (URP) project with live mesh painting in play mode.
- MeshPainter.cs: paint a SkinnedMesh with the mouse, seamless across
UV islands via 3D-space painting, GPU and CPU backends (switchable),
edge-padding/dilation against bilinear seam bleed
- FrameRateLimiter.cs: simple frame rate limiting component
- MeshPaintBrush / MeshPaintDilate shaders for the GPU paint path
- Unity-specific .gitignore and .gitattributes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>