190 lines
15 KiB
Markdown
190 lines
15 KiB
Markdown
# Research: physics player bodies + hugging/contact in VR
|
||
|
||
Fourth research pass for VR Messs (Godot 4.7, C#, physics hands = force-clamped rigid palms
|
||
chasing controllers at 90 N; placeholder box rig = procedural torso + 2-bone analytic arms,
|
||
no Skeleton3D yet; Box3D physics server, joints: pin/hinge/slider/cone-twist→weld-patched).
|
||
Goal: player arms+chest react physically — hugging characters, body reacting when grabbed.
|
||
Label: [S] = sourced, [I] = inference. See also `vr-arm-ik.md`, `vr-arm-ik-deep.md`,
|
||
`vr-grabbing.md`, `vr-two-handed-grab.md`.
|
||
|
||
## 1. Prior art — player body physics in VR
|
||
|
||
- [S] **Boneworks/Bonelab** (GDC 2020 "Heuristic Based Approaches to Physics Systems"; coverage:
|
||
https://www.gamedeveloper.com/design/how-classical-game-mechanics-and-physics-converge-in-vr-hit-i-boneworks-i/,
|
||
Marrow wiki: https://boneworks.fandom.com/wiki/1Marrow_Interaction_Engine): the ENTIRE virtual
|
||
body is one physics object, 82 kg, "no infinite forces" — every interaction draws on the body's
|
||
force budget; jumping = physically thrusting feet down; exploits die because classical mechanics
|
||
is the ruleset. Arms = 2-bone chains driven by constraints toward controller targets with a
|
||
heuristic force/velocity limit; over budget → the BODY moves, not the hand. Internal solver
|
||
details beyond that are not public. Motion sickness is the accepted cost: players report it as
|
||
one of the most nauseating VR games because the physics body can shove the camera off the real
|
||
head pose (https://www.resetera.com/threads/highly-anticipated-vr-title-boneworks-is-a-collection-of-vr-sins.158449/page-5).
|
||
- [S] **HL:Alyx** shipped HANDS ONLY, deliberately — IK arms mislead because there is no
|
||
proprioception for elbow/shoulder (dev commentary:
|
||
https://combineoverwiki.net/wiki/Developer_commentary/Half-Life:_Alyx). The strongest evidence
|
||
that "collision-enabled limbs" were considered not worth it.
|
||
- [S] **Stormland** (Insomniac): fully ANIMATED rendered arms + hip/shoulder holsters that ground
|
||
body awareness; body position handled by "invisible logic" for player intent, not a simulated
|
||
chain (https://roadtovr.com/stormland-behind-the-scenes-insomniac-games/2/). Kinematic body,
|
||
fake arms — feels great, can't hug anyone.
|
||
- [S] **Vertigo 2**: solo dev moved to a full physics-driven first-person body + hand physics and
|
||
committed to "full physics going forward" (devblog:
|
||
https://www.reddit.com/r/ValveIndex/comments/d48pex/vertigo_2_devblog_new_first_person_body_hand);
|
||
no postmortem numbers published. Proof one person can ship it in a standard engine.
|
||
- [S] **Open-source / community implementations**: Valem's Boneworks-style full-body-physics Unity
|
||
tutorial series (https://www.youtube.com/watch?v=D9qQb3EvU8c — rigidbody torso + jointed limbs
|
||
chasing trackers); RealMotionVR physics player controller
|
||
(https://github.com/pierricklyons/real-motion-vr); community full-body-physics WIPs with the
|
||
recurring pattern "rigidbody hands diverge from ghost hands → haptic + visual snap-back"
|
||
(https://www.reddit.com/r/Unity3D/comments/9sjsm9/vr_fullbody_physics_because_im_tired_of_reaching/,
|
||
https://www.reddit.com/r/ValveIndex/comments/ircdm3/wip_full_body_physics_high_fidelity_hands_in).
|
||
[I] No repo named "Hurdy" surfaced in any search — likely misremembered.
|
||
- [I] Pattern across all of them: simulate at most ONE powered body (the chest/torso root) driven
|
||
toward the HMD, and let limbs be either kinematic (Stormland/Alyx) or weakly-driven physics
|
||
chains (Boneworks). Nobody ships a fully self-colliding humanoid player rig — self-collision +
|
||
comfort + tuning cost is why.
|
||
|
||
## 2. Active ragdoll / puppet techniques (how pose-tracking-on-physics is done)
|
||
|
||
- [S] **Canonical recipe** (Gang Beasts-style; https://www.reddit.com/r/Unity3D/comments/3v6kt8/does_anyone_know_how_gang_beasts_physics_are):
|
||
semi-procedural blend of keyframed pose-matching + active ragdoll. Implementation lineage:
|
||
- Joint drive to animated "master" pose: duplicate physical body, each ConfigurableJoint's
|
||
angular drive target-rotation = the animated counterpart's rotation
|
||
(https://github.com/sergioabreu-g/active-ragdolls).
|
||
- PD control per joint: proportional-derivative torques toward target pose — the standard
|
||
formulation (EggyStudio Unity.Humanoid.ActiveRagdoll, "follows an animation using a simple
|
||
PD controller" with configurable joints, weakening drives on collision:
|
||
https://github.com/CanTalat-Yakan/Unity.Humanoid.ActiveRagdoll).
|
||
- Research tier: DReCon (Bergamin et al. 2019, ACM TOG) = motion matching picks the target
|
||
pose, RL-trained policy applies PD torques + root drive for balance
|
||
(https://www.researchgate.net/publication/337117918_DReCon_data-driven_responsive_control_of_physics-based_characters);
|
||
SIMBICON-style feedback and stepping controllers for balance
|
||
(https://arxiv.org/html/2210.14730v1; survey: Geijtenbeek et al. 2012,
|
||
https://onlinelibrary.wiley.com/doi/abs/10.1111/j.1467-8659.2012.03189.x).
|
||
- Balance practicals: lock hips X/Z rotation so the ragdoll can't fall while still being pushed
|
||
(https://sergioabreu-g.medium.com/how-to-make-active-ragdolls-in-unity-35347dcb952d), or apply
|
||
an external upright torque/com-height controller — joint motors alone don't balance
|
||
(https://medium.com/@jacasch/balancing-of-active-ragdolls-in-games-367f146b25fb).
|
||
- Practical tips for making them look alive, not spastic:
|
||
https://www.gamedeveloper.com/design/8-tips-for-animating-active-ragdolls.
|
||
- [S] **Human Fall Flat** never published a technique talk (closest is design retrospectives);
|
||
the joint-motor active-ragdoll recipe above is the community-reconstructed equivalent
|
||
(https://www.reddit.com/r/godot/comments/1fnwu2v/how_to_make_an_active_ragdoll_using_joint_motors).
|
||
- [I] **Failure modes** (consistent across sources): too-high drive gains inject energy →
|
||
jitter/explosions at solver limits; too-low → mush that can't hold a pose; the balance layer is
|
||
the whole difficulty — pose tracking is easy, staying upright while pushed is not. Gain tuning
|
||
is per-body and iterative (tens of iterations), and (per wirewhiz Alyx-hands notes in
|
||
`vr-grabbing.md`) "overly aggressive joint values destabilize the sim" is a physics-server-level
|
||
truth, not engine-specific.
|
||
|
||
## 3. Hugging / close contact with characters in VR
|
||
|
||
- [S] **In-game examples are almost nonexistent.** The closest known artifact is a Unity dev
|
||
clip "Added arm physics so now you can hug stuff in VR!" — physics-driven arms colliding with
|
||
bodies produce a passable hug for free (https://www.reddit.com/r/Unity3D/comments/jnfau2/added_arm_physics_so_now_you_can_hug_stuff_in_vr);
|
||
"The Hug Game" makes the other player's arms the hug implement
|
||
(https://automaton-media.com/en/news/20220225-10037). No shipped AAA VR game has a simulated
|
||
embrace — the user's "not even Bonelab had it" observation is correct.
|
||
- [S] **VRChat avatar "hugging"** is theater, not physics: PhysBones are spring chains for
|
||
secondary motion that can collide but carry no character-to-character force exchange
|
||
(https://creators.vrchat.com/common-components/physbones); Contacts are overlap event triggers —
|
||
sender touches receiver → animator parameter — auto-placed on hand/finger colliders
|
||
(https://creators.vrchat.com/common-components/contacts). So VRChat hugs = arms clip through +
|
||
contact event plays an animation. It still sells, which is evidence contact EVENTS + reaction
|
||
matter more than force fidelity.
|
||
- [S] **HCI/haptics research on hugs** (what makes a hug read as a hug):
|
||
Hugvie — a hug-shaped pillow that improves conversation affect, i.e. the SHAPE of contact does
|
||
the work (https://eng.irl.sys.es.osaka-u.ac.jp/projects/hugvie; study:
|
||
https://www.semanticscholar.org/paper/3a11fff7f3945f1a103ef233aba2d46de1122f35);
|
||
HuggieBot — established design tenets of natural robotic hugging, haptic REACTIVITY (responding
|
||
during the hug) significantly improves perception (https://arxiv.org/html/2101.07679v1,
|
||
https://is.mpg.de/hi/projects/huggiebot-evolution-of-an-interactive-hugging-robot-with-visual-and-haptic-perception);
|
||
intra-hug gestures the huggee should respond to: holding, rubbing, patting, squeezing
|
||
(https://dl.acm.org/doi/fullHtml/10.1145/3526110);
|
||
"Anatomy of a Hug in Virtual Reality" (Deusdado & Antunes, Procedia CS 239, 2024) — hug =
|
||
wrap + pressure + duration, haptic presence over fidelity
|
||
(https://www.sciencedirect.com/science/article/pii/S187705092401528X).
|
||
- [I] Synthesis: a hug reads correctly when (1) your arms VISIBLY wrap (no clipping, no
|
||
IK explosion), (2) contact is mutual — you can push and feel resistance, (3) the other party
|
||
RESPONDS (pressure → squeeze-back, pat → shift). Force simulation provides 1+2 cheaply; 3 is
|
||
gameplay code reading contact events.
|
||
|
||
## 4. What sells contact — full sim vs pseudo-physics
|
||
|
||
- [S] Boneworks' GDC claim in essence: physics contact sells because forces are CONSISTENT
|
||
(one 82 kg budget, no infinite forces) — not because bones are individually simulated.
|
||
- [S] Alyx cut arm physics and shipped the best-feeling hands of its generation; Stormland faked
|
||
arms entirely and scored on body presence. Both prove partial approaches can carry immersion.
|
||
- [S] But neither can HUG: pseudo-physics limbs clip through characters by design, and clip = no
|
||
hug, no lean, no tug. Boneworks CAN be leaned on things and shove bodies with its chest.
|
||
- [I] Decision rule: pseudo-physics (kinematic torso collider + IK arms) is enough for
|
||
self-presence, NOT enough for contact mechanics. The minimum real-physics set for hugging is
|
||
exactly: one physics torso/chest collider + two physical arm segments (we already have palms)
|
||
with weak pose drives — i.e. an active-ragdoll-torso, not a full skeleton sim.
|
||
|
||
## 5. Recommended approach for VR Messs
|
||
|
||
Constraints: Box3D (pin/hinge/slider/weld-patched-cone-twist), placeholder box rig, no
|
||
Skeleton3D, physics hands exist. [I] throughout this section unless noted.
|
||
|
||
1. **Torso = one RigidBody3D (capsule/box), PD-driven toward an HMD-derived target** — position
|
||
from HMD, yaw from the torso-yaw spring already specced in `vr-arm-ik-deep.md`. Force-CLAMPED
|
||
chase (same 90 N-class budget pattern as the palms). This body grounds all contact: hug
|
||
pressure, tug response, door pushes. DO NOT weld the HMD to it — camera stays kinematic
|
||
(Boneworks' sickness lesson, §1); torso chases the camera, never the reverse.
|
||
2. **Arms phase 1 = visual-only 2-bone analytic IK (existing) + existing palm bodies.** Chest
|
||
contact comes from the torso body; arms don't need physics to hug at chest height. Palms
|
||
colliding with the NPC's body already provide "arms resist contact" below the face.
|
||
3. **Arms phase 2 (only if phase 1 reads as clipping) = active-ragdoll upper-arm/forearm
|
||
segments**: rigidbodies per segment, hinge joints, hinge MOTOR targets = the analytic IK
|
||
solution's angles, low gain + velocity cap (§2 recipe, adapted to Box3D's hinge motors).
|
||
Joint motors beat per-frame force application — let the solver own it (same lesson as
|
||
`vr-grabbing.md`). Skip self-collision entirely (torso↔arm excluded pairs); nobody notices.
|
||
4. **Hug detection = contact events, not force analysis**: both palms (or forearm segments) in
|
||
contact with NPC torso + player chest collider touching NPC torso + sustained ≥0.5 s →
|
||
"embracing" state; read total contact impulse for a pressure value. NPC response = squeeze
|
||
force ramp on the player torso body + reaction gestures (HuggieBot reactivity finding, §3).
|
||
Optional: fade the visual arms into a scripted wrap pose during the state — VRChat proves
|
||
players forgive clipped/faked hugs if the reaction is right.
|
||
5. **Grabbed/tugged**: free — any joint from an NPC/prop to the torso body makes the whole body
|
||
react, because the torso is now the anchored mass the palms were implicitly missing. Cap the
|
||
coupling force below the torso chase budget so tugs can't yank the camera frame (sickness).
|
||
6. **Box3D-specific risks**: [I] cone-twist is weld-patched → use hinge+motor for limb drives and
|
||
pin for torso coupling; verify hinge motor max-impulse behavior at 90 Hz before building on
|
||
it (the `godot-box3d-weld.md` patch is the precedent for upstreaming what's missing).
|
||
7. **Explicitly rejected**: full per-bone simulated player skeleton (§1 — nobody ships it;
|
||
comfort + tuning cost), VRChat-style event-only hugs (no mutual force = no resistance = hollow),
|
||
Go-Go stretch arms (rejected before in `vr-arm-ik.md`).
|
||
|
||
## 6. Nimso Studios' "Hybrid Presence" — the closest known full-arm-physics VR body (researched 2026-10-01)
|
||
|
||
Owner-pointer. Unity, CLOSED demos — no source, no Unity package (commenters asked; refused),
|
||
no written technical breakdown exists anywhere.
|
||
|
||
- [S] Itch: `https://nimsostudios.itch.io/hybrid-presence-samples2` — "The Hybrid Presence
|
||
system on the arms only" (Spideriini: web-swinging/wall-climbing with physics arms that
|
||
climb ledges, push off walls, slow you down). Dev's OWN admitted issues: "some small issues
|
||
with elbows and with stuttering hands" — i.e., the exact failure modes our research predicts
|
||
(elbow singularities, chase-gain jitter) persist even in the best-known implementation.
|
||
- [S] `https://nimsostudios.itch.io/hybrid-test-chamber-tech-demo` — physics-simulated
|
||
interactions (physical hands, grip points, two-handed weapons "using a Hybrid system"
|
||
blending primary-hand rotation with secondary-hand position), physics locomotion (sway/jog
|
||
detection from natural bounce frequency). Known issues: physics glitches "inherent to the
|
||
physics engine", shoulder logic UNIMPLEMENTED (butt stocks have no effect). For an FPS.
|
||
- [S] Channel `youtube.com/@NimsoStudios` — the technique lives only in videos: "IN-DEPTH VR
|
||
PHYSICS INTERACTIONS" parts 1–2 (`youtube.com/watch?v=tMDmwD1cQPg`,
|
||
`youtube.com/watch?v=BTlY8SWLtgo`), "Hybrid Muscle System – Fast VR Physics" (arm
|
||
force/strength model), "FLUID VR HAND ADAPTATION + Hand Tracking" (hands deform to fit
|
||
objects on contact), "Project TX – physics NPCs". Community framing: Boneworks-class body,
|
||
"muscle-like" force constraints driving simulated arms/body from the controllers.
|
||
- [S] Godot-land has NOTHING at this tier — the ceiling is XR Tools' kinematic PlayerBody
|
||
(`github.com/GodotVR/godot-xr-tools`) + physical-hands templates
|
||
(`github.com/jtnicholl/godot4-vr-physics-template`). A Godot full-physics body would be
|
||
novel; as reusable tech for the owner's second project that novelty is a feature.
|
||
- [I] Assessment feed: Nimso validates BOTH directions — full arm physics is achievable by
|
||
one person (samples are free and rated 4.8/5), AND its cost is visible in his own issue
|
||
lists (elbows, hand stutter, shoulder logic missing after years). His "muscle" language =
|
||
force-clamped chase drives, i.e. the same pattern as our PhysicsHands generalized to limbs;
|
||
"hybrid" = tracked targets + simulated bodies, which is ALSO our layer-3 architecture
|
||
(AGENTS.md). We are not inventing a new technique — we'd be porting a known-shaped one.
|