Soft grab (Nimso): ease the object into the hand (or the hand to the hold) before the weld
Light props (<= 6 kg) fly to the palm, static world / heavy things pull the hand; position only, ~0.1 s, never a snap. Welds no longer freeze a hover gap. Spike: 1 kg cube from 6 cm -> 1.5 mm, bar from 5 cm -> 1.2 cm (contact slop on a curved hold). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
83186f9676
commit
22159aa902
3 files changed
+198
-12
No files matched your search
@@ -119,6 +119,8 @@ public partial class RagdollSpike : Node3D
|
||||
_phases.Add(("jump: a tap from a real crouch beats a standing tap", Rest, t => TickJump(0.45f, 0.05f), 4.5f, () => FinishJump(2)));
|
||||
_phases.Add(("looks down past vertical while crouched (body doesn't flip around)", Rest, TickLookDown, 5f, FinishLookDown));
|
||||
_phases.Add(("stick crouch lowers the body and the view, and stands back up", Rest, TickStickCrouch, 6f, FinishStickCrouch));
|
||||
_phases.Add(("soft grab: a 1 kg cube 6 cm off the palm is eased into the hand, then held", () => SetupSoftGrab(prop: true), TickSoftGrab, 3f, FinishSoftGrab));
|
||||
_phases.Add(("soft grab: a bar 5 cm off the palm — the hand goes to it", () => SetupSoftGrab(prop: false), TickSoftGrab, 3f, FinishSoftGrab));
|
||||
_phases.Add(("standing on a seesaw tips it (body weight reaches movable ground)", SetupSeesaw, _ => { }, 3f, FinishSeesaw));
|
||||
_phases.Add(("playground: swing board hangs, seesaw on its pivot, big plank grabbable", SetupPlayground, _ => { }, 2f, FinishPlayground));
|
||||
_phases.Add(("walks up an 18° ramp", () => SetupRamp(18f), _ => _stickVelocity = new Vector3(0f, 0f, -1.2f), 4f, () => FinishRamp(true)));
|
||||
@@ -782,6 +784,83 @@ public partial class RagdollSpike : Node3D
|
||||
&& Mathf.Abs(_ragdoll.Pelvis.GlobalPosition.Y - _ragdoll.GroundY - _dropStand) < 0.05f;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- soft grab
|
||||
|
||||
private PhysicsBody3D _sgTarget;
|
||||
private SoftGrab _sg;
|
||||
private ConeTwistJoint3D _sgWeld;
|
||||
private float _sgGapAtWeld, _sgMaxSpeed, _sgHeldGap, _sgWeldTime;
|
||||
private bool _sgProp;
|
||||
|
||||
private void SetupSoftGrab(bool prop)
|
||||
{
|
||||
Rest();
|
||||
_sgProp = prop;
|
||||
_sg = null;
|
||||
_sgWeld = null;
|
||||
_sgGapAtWeld = _sgHeldGap = -1f;
|
||||
_sgMaxSpeed = 0f;
|
||||
_sgWeldTime = -1f;
|
||||
_sgTarget = null;
|
||||
}
|
||||
|
||||
// Right controller held still in front; at 1.5 s the target appears off the palm and grip is pressed.
|
||||
private void TickSoftGrab(float dt)
|
||||
{
|
||||
_measureFrom = float.MaxValue;
|
||||
if (!_ragdoll.Built || _needBuild)
|
||||
return;
|
||||
RigidBody3D hand = _ragdoll.Hand(1);
|
||||
if (_sgTarget == null && _t >= 1.5f)
|
||||
{
|
||||
Vector3 n = SoftGrab.PalmNormal(hand, 1);
|
||||
Vector3 surface = SoftGrab.PalmSurface(hand, 1);
|
||||
if (_sgProp)
|
||||
{
|
||||
RigidBody3D cube = MakeBox(Vector3.One * 0.08f, 1f, surface + n * (0.06f + 0.04f));
|
||||
cube.GravityScale = 0f; // "floating" just for the setup instant; gravity back on at the weld
|
||||
_sgTarget = cube;
|
||||
}
|
||||
else
|
||||
{
|
||||
StaticBody3D bar = new() { CollisionMask = 29, Position = surface + n * (0.05f + 0.025f) };
|
||||
bar.AddChild(new CollisionShape3D { Shape = new CylinderShape3D { Radius = 0.025f, Height = 1f } });
|
||||
_stage.AddChild(bar);
|
||||
_sgTarget = bar;
|
||||
}
|
||||
return; // let the new body enter the space before querying it
|
||||
}
|
||||
if (_sgTarget == null)
|
||||
return;
|
||||
if (_sg == null && _sgWeld == null)
|
||||
_sg = SoftGrab.Begin(hand, 1, _sgTarget);
|
||||
if (_sg != null)
|
||||
{
|
||||
if (_sgTarget is RigidBody3D rb)
|
||||
_sgMaxSpeed = Mathf.Max(_sgMaxSpeed, rb.LinearVelocity.Length());
|
||||
_sgMaxSpeed = Mathf.Max(_sgMaxSpeed, hand.LinearVelocity.Length());
|
||||
if (_sg.Step(dt))
|
||||
{
|
||||
_sgGapAtWeld = _sg.Gap;
|
||||
_sgWeldTime = _t;
|
||||
_sg = null;
|
||||
_sgWeld = new ConeTwistJoint3D { Position = PropGrabber.PalmPoint(hand, 1), NodeA = hand.GetPath(), NodeB = _sgTarget.GetPath(), SwingSpan = 0f, TwistSpan = 0f, Bias = 0f, ExcludeNodesFromCollision = true };
|
||||
_stage.AddChild(_sgWeld);
|
||||
if (_sgTarget is RigidBody3D cube)
|
||||
cube.GravityScale = 1f;
|
||||
_ragdoll.SetHeld(1, _sgTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool FinishSoftGrab()
|
||||
{
|
||||
float held = _sgTarget == null ? -1f : (SoftGrab.PalmSurface(_ragdoll.Hand(1), 1) - _sgTarget.GlobalPosition).Length() - (_sgProp ? 0.04f : 0.025f);
|
||||
GD.Print($"RAGDOLL: soft grab ({(_sgProp ? "1 kg cube" : "static bar")}): welded after {(_sgWeldTime - 1.5f):F3} s with gap {_sgGapAtWeld:F4} m, fastest motion {_sgMaxSpeed:F2} m/s, held gap at the end {held:F3} m, snaps {NewSnaps}");
|
||||
_ragdoll.SetHeld(1, null);
|
||||
return _finite && NewSnaps == 0 && _sgWeldTime > 0f && _sgWeldTime - 1.5f < 0.25f && _sgGapAtWeld < (_sgProp ? 0.01f : 0.015f) && _sgMaxSpeed < 3.5f && held < 0.02f;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------- jump
|
||||
|
||||
private float _jumpStand, _jumpApex, _jumpEyeErr, _tapApex;
|
||||
|
||||
Reference in new issue
Block a user