We have a series of VG onboarding tasks to show how to tackle different practical use cases using VirtualGrasp in a VR application. In VirtualGrasp SDK, they are packed in VirtualGrasp\Scenes\onboarding.

Task Description

If this video shows "This video is unavailable," please try to refresh the page.

Interaction behaviors wanted

  • We want to close the water bottle with the cap screwed on.
  • Neither the water bottle nor the cap are physical object, so can not use Unity‚Äôs physical joint support.

Tips for VR developers

  • VG_Articulation support creating joints on non-physical objects (objects without Rigidbody or ArticulationBody).


In VirtualGrasp SDK, we packed the solution of this task in VirtualGrasp/Scenes/onboarding.


using UnityEngine;
using VirtualGrasp;
using System.Collections.Generic;

 * AssembleVGArticulation shows as a tutorial on how to use the VG_Controller.ChangeObjectJoint function for
 * assemble and dissemble non-physical objects (objects without rigid body or articulation body).
public class AssembleVGArticulation : MonoBehaviour
    public Transform m_newParent = null;
    public Transform m_desiredPose = null;
    public float m_assembleDistance = 0.05f;
    public float m_disassembleDistance = 0.5f;
    public VG_Articulation m_assembleArticulation = null;

    private float timeAtDisassemble = 0.0F;
    private float assembleDelay = 1.0F;

    void Start()

    void Update()

    void assembleByJointChange()
        if ((Time.realtimeSinceStartup - timeAtDisassemble) > assembleDelay
           && (m_desiredPose.position - this.transform.position).magnitude < m_assembleDistance
           && VG_Controller.GetObjectJointType(this.transform, false) == VG_JointType.FLOATING)
            this.transform.SetPositionAndRotation(m_desiredPose.position, m_desiredPose.rotation);

            if (m_newParent != null)

            VG_Controller.ChangeObjectJoint(transform, m_assembleArticulation);

    void dessembleByJointChange()
        foreach (VG_HandStatus hand in VG_Controller.GetHands())
            if (hand.m_selectedObject == transform && hand.IsHolding()
                && VG_Controller.GetObjectJointType(transform) != VG_JointType.FLOATING)
                VG_Controller.GetSensorPose(hand.m_avatarID, hand.m_side, out Vector3 sensor_pos, out Quaternion sensor_rot);
                if (VG_Controller.GetObjectJointState(transform) == 0.0f
                    && (sensor_pos - hand.m_hand.position).magnitude > m_disassembleDistance)

                    timeAtDisassemble = Time.realtimeSinceStartup;

is the script showing how to use API function ChangeObjectJoint and RecoverObjectJoint to attach and unattach the cap on to the bottle.