Arms playtest-1 fixes: open-loop torso lean (chest hunting), hand-driven elbow pole + height cap, held-prop arm collision exceptions

- Lean computed from PhysicsTorso.NominalTarget/TargetBasis, not the body's own shoulders:
  the closed loop made the chest hunt (spike: |v| 1.1 -> 0.019 m/s, lean range 2.7 cm -> 0.9 mm)
- Elbow on its IK circle, 75% hand-axis (forearm continues behind the wrist), bounded-rate
  rotation smoothing (no flips), capped at max(shoulder, wrist) + 5 cm
- PhysicsArms.SetHeld: held prop ignores that side's arm segments (PropGrabber calls it)
- ArmSpike: stretch settle, hug elbows out (0.17 m vs 0.02 m old pole), held-anvil stability;
  all six spikes PASS x3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
FoxyzandClaude Opus 5.5 committed 2026-10-02 00:25:50 +03:00
1 parent 7589b13aba
commit 464cda2f71
6 files changed
+288 -65

No files matched your search

+4
View File
@@ -16,6 +16,7 @@ public partial class PropGrabber : Node
private XRController3D _left;
private XRController3D _right;
private PhysicsArms _arms;
private readonly RigidBody3D[] _held = new RigidBody3D[2];
private readonly ConeTwistJoint3D[] _joints = new ConeTwistJoint3D[2];
@@ -30,6 +31,7 @@ public partial class PropGrabber : Node
_instance = this;
_left = GetNode<XRController3D>("../XROrigin3D/LeftHand");
_right = GetNode<XRController3D>("../XROrigin3D/RightHand");
_arms = GetNodeOrNull<PhysicsArms>("../PhysicsArms");
}
public static bool IsGrabbing(XRController3D controller) =>
@@ -66,6 +68,7 @@ public partial class PropGrabber : Node
Vector3 pivot = PalmPoint(handBody, hand);
_joints[hand] = MakeWeld(handBody, prop, pivot, RigidWeldBias);
_localAnchor[hand] = prop.GlobalTransform.AffineInverse() * pivot;
_arms?.SetHeld(hand, prop);
GD.Print($"PropGrabber: grabbed '{prop.Name}' ({prop.Mass:0.###} kg, {(hand == 0 ? "left" : "right")}{(_held[other] == prop ? ", two-handed" : "")})");
}
}
@@ -182,6 +185,7 @@ public partial class PropGrabber : Node
private void DestroyJoint(int hand)
{
_arms?.SetHeld(hand, null);
if (_joints[hand] != null && IsInstanceValid(_joints[hand]))
_joints[hand].QueueFree();
_joints[hand] = null;