Body physics Stage 2: physical arm segments (chase-driven upper arm + forearm, hierarchical budgets, layer 5)
- PhysicsArms: per side 2.0 kg upper arm + 1.2 kg forearm RigidBody3D PD-chasing their analytic 2-bone IK pose, solved per physics tick from the physical chest shoulders to the physical hands; no joints (Box3D has no usable shoulder/wrist joint; AGENTS forbids joints between tracked bodies). Budgets from a 60 kg mass stat: hand 90 < forearm 180 < upper arm 360 < chest 2400 N. Owns calibration + reach budget (moved from BodyRig); 1 m snap, non-finite reset, BodyMath.RotationError servo. - Layer 5 = player arms (mask 1); props/table/floor masks include it; no self-collision. - BodyRig: visuals only, arms drawn shoulder -> physical elbow -> wrist. - ArmSpike: track gap 0, swing lag <= 6 cm, arm pushes prop with hand clear, forearm blocked by bar without tunneling and quiet when pinned, teleport snap, NaN reset — PASS x3. - CollapseSpike now runs the full body (49/49 x3); all six spikes PASS x3. - HANDOFF/AGENTS: Stage 2 entry (item 10), layers, tuning table, Stage 2b next steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cb518999e5
commit
7589b13aba
11 files changed
+708
-174
No files matched your search
@@ -1,7 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using Godot;
|
||||
|
||||
// Headless regression for the Stage-1 playtest collapse (2026-10-01). Two families:
|
||||
// Headless regression for the Stage-1 playtest collapse (2026-10-01), now with the full Stage-2
|
||||
// body (chest + PhysicsArms + hands). Two families:
|
||||
// - Stacking: seated chest overlapping the static table, 50 kg anvil rigid-welded to two
|
||||
// chase hands, the logged grab sequence (L, R two-handed, L release, L re-grab), the real
|
||||
// PropShop with the chest plowing through the props. Did NOT reproduce the NaN — kept as
|
||||
@@ -39,6 +40,7 @@ public partial class CollapseSpike : Node3D
|
||||
private Node3D _world;
|
||||
private Node3D _head;
|
||||
private PhysicsTorso _torso;
|
||||
private PhysicsArms _arms;
|
||||
private readonly RigidBody3D[] _hands = new RigidBody3D[2];
|
||||
private readonly Node3D[] _targets = new Node3D[2];
|
||||
private readonly ConeTwistJoint3D[] _welds = new ConeTwistJoint3D[2];
|
||||
@@ -189,6 +191,9 @@ public partial class CollapseSpike : Node3D
|
||||
_world.AddChild(_targets[h]);
|
||||
_targetBase[h] = handPos;
|
||||
}
|
||||
|
||||
_arms = new PhysicsArms { HeadSource = _head, Torso = _torso, HandLeft = _hands[0], HandRight = _hands[1] };
|
||||
_world.AddChild(_arms);
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
@@ -258,6 +263,15 @@ public partial class CollapseSpike : Node3D
|
||||
Check("handR", _hands[1]);
|
||||
if (_anvil != null)
|
||||
Check("anvil", _anvil);
|
||||
for (int side = 0; side < 2; side++)
|
||||
{
|
||||
if (_arms.UpperArm(side) == null)
|
||||
continue;
|
||||
Check($"upper arm {side}", _arms.UpperArm(side));
|
||||
Check($"forearm {side}", _arms.Forearm(side));
|
||||
if (_arms.Forearm(side).LinearVelocity.Length() > RunawaySpeed || _arms.UpperArm(side).LinearVelocity.Length() > RunawaySpeed)
|
||||
Fail($"arm {side} runaway");
|
||||
}
|
||||
foreach (Node n in GetTree().GetNodesInGroup("prop"))
|
||||
{
|
||||
if (n is not RigidBody3D prop || prop.IsQueuedForDeletion())
|
||||
|
||||
Reference in new issue
Block a user