I am trying to create my own scripts called DistanceGrabber for my hands and DistanceGrabbable for the objects I want to be able to grab from a distance.
what I made kind of works but the laser pointer script is making me have to release the grip button first before executing the onDistanceGrab function in DistanceGrabbable script, so I had to “double click” rapidly and hold the grip the second time to be able to hold the object in the hand or else it will just fall to the ground.
how do you disable the line when the laser is not pointing at a grabbable object?
public class DistanceGrabber : MonoBehaviour
private SteamVR_LaserPointer laserPointer;
private Hand hand;
laserPointer = GetComponent<SteamVR_LaserPointer>();
hand = GetComponent<Hand>();
laserPointer.PointerIn += PointerInside;
laserPointer.PointerOut += PointerOutside;
laserPointer.PointerClick += PointerClick;
//interactable = GetComponent<Interactable>();
public void PointerClick(object sender, PointerEventArgs e)
if (e.target.GetComponent<DistanceGrabbable>() != null)
public void PointerInside(object sender, PointerEventArgs e)
if (e.target.GetComponent<Interactable>() != null)
laserPointer.active = true;
public void PointerOutside(object sender, PointerEventArgs e)
if (e.target.GetComponent<Interactable>() == null)
laserPointer.active = false;
public class DistanceGrabbable : MonoBehaviour
protected Rigidbody rb;
protected bool originalKinematicState;
protected Transform originalParent;
private void Awake()
rb = GetComponent<Rigidbody>();
originalParent = transform.parent;
originalKinematicState = rb.isKinematic;
public void onDistanceGrab(Hand hand)
rb.isKinematic = true;
private void OnDetachedFromHand(Hand hand)
rb.isKinematic = false;
@HelloPeopIe I have a solution to your problem. My code doesn’t use a visible laser pointer, but instead, the objects I am pointing at have a child object with a SteamVR hover highlight material, as shown in the screenshot below.
but once you have that cube as a child of your base object, here is the code:
public class DistanceGrab : MonoBehaviour
public Transform pointer;//the transform the laser starts at
public LayerMask thingsWeCanGrab;//things we can grab
Hand hand;//our hand
bool isAttached = false;//do we have something in our hand?
GameObject attachedObject = null;//what do we have in our hand
Blank blank;//blank script
// Start is called before the first frame update
hand = GetComponent<Hand>();//get our hand
// Update is called once per frame
//raycast and check if our hand is empty
if (Physics.Raycast(pointer.position, pointer.forward, out hit, 10f, thingsWeCanGrab) && hand.currentAttachedObject == null)
Interactable interactable = hit.collider.gameObject.GetComponent<Interactable>();
SteamVR_Input_Sources source = hand.handType;
//are we pressing grip and trigger?
if (hand.grabGripAction[source].state == true && hand.grabPinchAction[source].state == true)
//does the interactable component exist?
if (interactable != null)
//move the object to your hand
interactable.gameObject.GetComponent<Rigidbody>().AddRelativeForce(Vector3.forward * 500, ForceMode.Force);
attachedObject = interactable.gameObject;
isAttached = true;
//attaching to hand is in the late update function
blank = hit.collider.gameObject.GetComponentInChildren<Blank>();
blank.gameObject.GetComponent<MeshRenderer>().enabled = true;
blank.gameObject.GetComponent<MeshRenderer>().enabled = false;
private void LateUpdate()
//did we get an object to our hand during this update?
//attach the object
attachedObject = null;
isAttached = false;
Hey man your code helped me earlier when I tried to implement the same thing. However after testing your code I found that the laser pointer had a lot of issues and I eventually came up with the same conclusion as rgbeans that a Raycast hit would work better.
However I’m assuming you have included the SteamVR_LaserPointer.cs as a laser to guide the user. Unfortunately turning the script on or off is a hassle and doesn’t really work:
The solution around this would be to change the thickness of the laser when the raycast hits the specific object.
if (Physics.Raycast() hits the object) or public void PointerInside(object sender, PointerEventArgs e)
laserPointer.thickness = 0.002f;
laserPointer.thickness = 0;
If you need anymore help hmu.