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.
and also
how do you disable the line when the laser is not pointing at a grabbable object?
My setup:
Unity 2019.2.6f1
SteamVR 2.0
Oculus Rift
DistanceGrabber script:
public class DistanceGrabber : MonoBehaviour
{
private SteamVR_LaserPointer laserPointer;
private Hand hand;
void Awake()
{
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)
{
e.target.GetComponent<DistanceGrabbable>().onDistanceGrab(hand);
}
}
public void PointerInside(object sender, PointerEventArgs e)
{
if (e.target.GetComponent<Interactable>() != null)
{
hand.ShowGrabHint();
hand.IsStillHovering(e.target.GetComponent<Interactable>());
laserPointer.active = true;
}
}
public void PointerOutside(object sender, PointerEventArgs e)
{
if (e.target.GetComponent<Interactable>() == null)
{
hand.HideGrabHint();
laserPointer.active = 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:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR.InteractionSystem;
using Valve.VR;
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
void Start()
{
hand = GetComponent<Hand>();//get our hand
}
// Update is called once per frame
void Update()
{
//raycast and check if our hand is empty
RaycastHit hit;
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.transform.LookAt(transform);
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;
}
else
{
blank.gameObject.GetComponent<MeshRenderer>().enabled = false;
}
}
private void LateUpdate()
{
//did we get an object to our hand during this update?
if (isAttached)
{
//attach the object
hand.AttachObject(attachedObject, GrabTypes.Grip);
attachedObject = null;
isAttached = false;
}
}
}
@HelloPeopIe
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: