Play a dedicated falling animation when the player is airborne and
descending past a scale-aware velocity threshold.
- PlayerCharacterController: new IsFalling state + Fall Animation Speed
threshold (true only when !grounded && !wallClimbing && descending,
scaled via CapsuleScale); explicitly false during wall/ceiling climb.
- PlayerPose: per-pose Fall Clip + Fall Clip Speed (mirrors walk/run).
- PlayerPoseController: select the fall clip while falling, fall back to
the idle clip when a pose has none (no regression).
- Author content: Paintman-Fall.anim assigned to Pose_Idle; UMotion
project, Player prefab and scene authoring.
- Docs: check off the fall animation in GAME_DESIGN.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When running backwards toward the camera into a wall, the grab decided on
the camera-relative world direction (S pushes into the wall -> grab) while
the base release decided on the raw S axis (v < 0 -> immediately let go),
causing a per-frame grab/release flicker.
Mirror the existing _wallStrafeSign A/D latch with a new _wallClimbSign:
the camera picks, per climb-key press, which of W/S climbs up (the one
pushing into the wall) via Dot(camForward, wallNormal) and latches it.
All up/down tests now run through the effective climb axis vEff -
wall->ceiling handoff, top-out detach/hop, the alongSurface mapping and
the base release - so grab and release can no longer contradict each
other. Reset on grab and in ExitWallClimb. Facing the wall and grabbing
with W is unchanged (vEff == v).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce a FirstPersonController / FirstPersonMode pair (mirroring the
free-cam mode) wired into the GameModeManager Tab cycle. In first person the
mesh is hidden, the eye sits on CameraTarget plus a per-pose
firstPersonCameraTargetYOffset, and the character body yaw is driven to match
the camera via a new single-writer FaceYaw hook on PlayerCharacterController.
Also includes user content edits (poses, prefabs, scene) carried along.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FreeCamController: ease movement via dt-correct Vector3.SmoothDamp on a world-space velocity (accel/decel ramp) and lag the look with Mathf.SmoothDampAngle. Both are framerate-independent and collapse to instant at smoothTime 0; smoothed state is snapped on activation (SyncToCurrentView) so entering freecam never jumps to catch up.
Bundles accumulated deferred work: PlayerScaler uniform-scale helper, scale-aware wall/ceiling climb probes and the double-scale skinned-collider bake fix, plus user content authoring (Sit pose + animation, font SDF, scene/prefab edits).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
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 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>
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>
- 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>
- Smooth acceleration/deceleration on ground and air movement
- Interpolated scroll zoom and low-pass smoothed orbit rotation
- Drive Animator "Running" bool while moving on the ground
- Add Paintman animator controllers and animation clips
- Update README and GAME_DESIGN docs for sprint, accel, camera smoothing and animator hookup
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Detach back to grounded movement when the climbed face flattens into
walkable ground or walkable ground sits below the feet, testing an
explicit downward probe instead of isGrounded (which the standoff
correction can falsify by lifting the capsule off the surface). Top-out
now applies an upward hop so holding W carries the player over the lip
instead of dropping back onto the steep face and re-grabbing, and a
shared re-grab cooldown spans the hop to prevent detach/re-grab buzzing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reuse the climb mode for ceilings (surface normal pointing down):
grab by jumping up into a ceiling or by climbing a wall up into an
overhang. The body stays upright and crawls camera-relative in the
horizontal plane; jump or a ceiling edge releases into a fall.
Generalize the wall probe to use the capsule's support extent
(radius sideways, half-height vertically) so the ceiling gap is correct.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the dead-beat-with-deadzone perpendicular controller with an
exponential follow that targets one skin-width beyond the offset, so the
capsule never penetrates the wall and the controller's depenetration no
longer fights back. Removes the quantizing deadzone that caused stepping.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Strafe (A/D) along the wall's horizontal tangent instead of the live
camera-right vector to stop the sideways jitter from the orbit feedback loop.
- Detach from the wall once the character reaches the ground (gated so it
only triggers after the climb has left the ground).
- Dead zone on the perpendicular offset controller to suppress depenetration buzz.
- Grab the wall only when actively pushing into it (wallGrabMinPush), preventing
re-grab at the wall base.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- W/S climb straight up/down at a constant speed (camera pitch no longer
tilts or slows them); the camera only drives A/D strafe along the wall.
- The body now always faces the wall. Holding LMB and dragging sets the
wall pose: vertical drag leans out from / back to the wall (offset eases
back to zero while moving, never detaches), horizontal drag turns the
body (yaw held until leaving the wall, eased back by ground rotation).
- Pause the camera orbit while dragging the wall pose (LookSuppressed).
- Drop the camera-to-wall angle logic and the old approach/detach-distance
model; add wallMaxOffset, wallOffsetSensitivity, wallOffsetReturnSpeed
and wallRotateSensitivity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reduce comments to non-obvious "why" notes and convert UnityEngine.Object
null checks to implicit bool (if (obj) / if (!obj)). Input System devices
(Mouse.current, Keyboard.current) and plain arrays keep explicit != null.
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>
- 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>