Fix cylinder wall-climb strafe lock and add terrain pipette support

- 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>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-06-24 22:33:29 +02:00
1 parent 85bd7c7791
commit 9dab4a742e
6 files changed
+1153 -27

No files matched your search

+17 -1
View File
@@ -160,6 +160,7 @@ public class PlayerCharacterController : MonoBehaviour
private float _lostContactTimer;
private float _wallOffset; // current lean-out distance from the wall (mouse drag)
private float _wallYaw; // body yaw offset from facing the wall (mouse drag); held until leaving
private int _wallStrafeSign; // latched sideways direction (camera picks it once per strafe); 0 = unlatched
private bool _offsetDragging; // true while the offset/rotation is being set (pauses camera orbit)
private bool _climbLeftGround; // true once the capsule has left the ground while climbing (enables ground-detach)
private readonly RaycastHit[] _wallProbe = new RaycastHit[8];
@@ -365,6 +366,7 @@ public class PlayerCharacterController : MonoBehaviour
_slideSpeed = 0f;
_wallOffset = 0f;
_wallYaw = 0f;
_wallStrafeSign = 0;
_climbLeftGround = false;
}
}
@@ -447,8 +449,21 @@ public class PlayerCharacterController : MonoBehaviour
if (wallUp.sqrMagnitude > 1e-6f) wallUp.Normalize();
Vector3 wallRight = Vector3.Cross(_wallNormal, wallUp);
if (wallRight.sqrMagnitude > 1e-6f) wallRight.Normalize();
if (cameraTransform && Vector3.Dot(cameraTransform.right, wallRight) < 0f)
// Pick the strafe sign ONCE from the camera when a strafe begins, then hold it.
// Re-deciding it every frame flips wallRight while rounding a curved (cylindrical)
// wall: exactly at 90 deg to the camera the dot crosses zero, so the sideways input
// inverts frame-to-frame and you lock there, jittering back and forth. Latching keeps
// a strafe continuous around the curve; it resets when the strafe input releases so
// the next one re-syncs to the camera.
bool strafing = Mathf.Abs(h) > 1e-4f;
if (!strafing)
_wallStrafeSign = 0;
else if (_wallStrafeSign == 0)
_wallStrafeSign = (cameraTransform && Vector3.Dot(cameraTransform.right, wallRight) < 0f) ? -1 : 1;
if (_wallStrafeSign < 0)
wallRight = -wallRight;
alongSurface = wallUp * v + wallRight * h;
}
if (alongSurface.sqrMagnitude > 1f) alongSurface.Normalize();
@@ -760,6 +775,7 @@ public class PlayerCharacterController : MonoBehaviour
_verticalVelocity = 0f;
_wallOffset = 0f;
_wallYaw = 0f;
_wallStrafeSign = 0;
_offsetDragging = false;
_climbLeftGround = false;
_mantling = false;