reckfellENGINE

XRHandModifier3D

Apply hand joints to named skeleton bones.

On this page
class XRHandModifier3DReckfellSharpInherits SkeletonModifier3D

XRHandModifier3D runs under Skeleton3D. It matches Left/Right-prefixed Humanoid bones according to tracker hand, such as LeftHand and LeftIndexProximal. Names and hierarchy must match before assessing deformation of a real model.

Full changes positions and rotations; RotationOnly changes rotations. Transforms are relative to parent joints and positions receive skeleton MotionScale. After a valid update, HasTrackingData=false reapplies cached pose. An invalid Palm with HasTrackingData=true instead skips modification; these are different cases.

Modifier output is temporary: read poses inside ModificationProcessed before Skeleton3D restores its base pose. This example stores a copy; LastModified can become stale when the modifier is disabled or the source disappears:

C#
using Reckfell;

public partial class HandPoseProbe : Entity
{
    [Export] public Skeleton3D Skeleton { get; set; } = null!;
    [Export] public XRHandModifier3D Modifier { get; set; } = null!;
    [Export] public int Bone { get; set; }
    public Transform3D LastModified { get; private set; } = Transform3D.Identity;

    public override void _Ready()
    {
        if (Skeleton is null || Modifier is null || Modifier.GetSkeleton() != Skeleton
            || Bone < 0 || Bone >= Skeleton.GetBoneCount())
        {
            ReckfellApi.PushError("HandPoseProbe: assign a matching skeleton, modifier and bone index.");
            return;
        }
        Modifier.ModificationProcessed += Capture;
    }
    private void Capture() => LastModified = Skeleton.GetBonePose(Bone);
    public override void _ExitTree()
    {
        if (Modifier is not null && ReckfellObject.IsInstanceValid(Modifier))
            Modifier.ModificationProcessed -= Capture;
    }
}

Important source limitation: the ORIENTATION_VALID scan does not become a per-child validity guard before application. Partially invalid child data was not accepted by this test; used joints and parents need a consistent valid set. Active=false disables processing. Do not hide invalidity by manually substituting flags on a real provider.

Fourteen checks used a real Skeleton3D, all 26 matched bones and synthetic joints. Modes, cache, MotionScale, tracker changes and the exact HandPoseProbe were exercised. Real hands, skin weights, deformation, animation blending and image quality were not checked. Setup and pinch: hand tracking.

Declarations checked against C# SDK 1.0.0. Expand a name to see declarations and documentation.

Constructors1

XRHandModifier3DConstructor
# XRHandModifier3D
C#
public XRHandModifier3D();

Creates a modifier with the left HandTracker and BoneUpdate=Full. Parent under Skeleton3D with matching bone names and an XRHandTracker provider. Creates no model, skin weights, collision or XR session.

Properties2

BoneUpdateProperty
# BoneUpdate
C#
public XRHandModifier3D.BoneUpdateEnum BoneUpdate { get; set; }

Update mode, initially Full. Full applies relative positions and rotations; RotationOnly leaves base bone positions and applies rotations. Input positions are multiplied by skeleton MotionScale, not automatically by WorldScale. Whole-hand data loss can reapply the previous relative pose.

HandTrackerProperty
# HandTracker
C#
public StringName HandTracker { get; set; }

XRHandTracker name, initially /user/hand_tracker/left. Inside the tree the setter rebuilds bone mapping and clears cached relative transforms even when repeating the name. Do not assign every frame. Creates no tracker and enables no hardware tracking.

Methods4

GetBoneUpdateXRHandModifier3D.BoneUpdateEnum
# GetBoneUpdate
C#
public XRHandModifier3D.BoneUpdateEnum GetBoneUpdate();

Configured Full/RotationOnly mode. Neither tracking status nor proof of successful skeleton processing.

Returns XRHandModifier3D.BoneUpdateEnum

Stored bone mode.

GetHandTrackerStringName
# GetHandTracker
C#
public StringName GetHandTracker();

Configured tracker name; does not establish presence or fresh data.

Returns StringName

Stored tracker name.

SetBoneUpdatevoid
# SetBoneUpdate
C#
public void SetBoneUpdate(XRHandModifier3D.BoneUpdateEnum boneUpdate);

Update mode, initially Full. Full applies relative positions and rotations; RotationOnly leaves base bone positions and applies rotations. Input positions are multiplied by skeleton MotionScale, not automatically by WorldScale. Whole-hand data loss can reapply the previous relative pose.

Parameters
NameTypeDefault
boneUpdateXRHandModifier3D.BoneUpdateEnum—
boneUpdate

Full or RotationOnly; Max is the bound, not a mode. The native setter checks bounds.

SetHandTrackervoid
# SetHandTracker
C#
public void SetHandTracker(StringName trackerName);

XRHandTracker name, initially /user/hand_tracker/left. Inside the tree the setter rebuilds bone mapping and clears cached relative transforms even when repeating the name. Do not assign every frame. Creates no tracker and enables no hardware tracking.

Parameters
NameTypeDefault
trackerNameStringName—
trackerName

Name of a left/right or custom registered XRHandTracker; repeating the in-tree setter also resets the cache.

XRHandModifier3D.BoneUpdateEnum

ValueDescription
Full = 0

The skeleton's bones are fully updated (both position and rotation) to match the tracked bones.

Max = 2

Represents the size of the XRHandModifier3D.BoneUpdateEnum enum.

RotationOnly = 1

The skeleton's bones are only rotated to align with the tracked bones, preserving bone length.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.