Hey everyone,
Just came to this forum for a completely unrelated reason and came across this thread. Coincidentally just solved this problem this week to build a grappling hook in the vanilla SteamVR 2.0 unity plugin. Proof:
The trick was getting steamVR to interact with the obi particles. Here's my ROUGH, unpolished code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Obi;
using Valve.VR;
[RequireComponent(typeof(ObiSolver))]
public class RopeClimb : MonoBehaviour
{
public ObiSolver solver;
protected Valve.VR.InteractionSystem.VelocityEstimator velocityEstimator;
public GameObject Player;
public float releaseVelocityTimeOffset = -0.011f;
private CharacterController m_CharacterController;
private bool detectingCollisions = true;
private Valve.VR.InteractionSystem.Hand draggingHand = null;
void Start()
{
m_CharacterController = Player.GetComponent<CharacterController>();
}
void Update()
{
// subscribe to collision
if (detectingCollisions == true) {
solver.OnCollision += Solver_OnCollision;
detectingCollisions = false;
}
// only set upon successful collision + grip
if (draggingHand != null) {
DragMove(draggingHand);
}
}
void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
{
var world = ObiColliderWorld.GetInstance();
foreach (Oni.Contact contact in e.contacts)
{
// this one is an actual collision:
if (contact.distance < 0.01)
{
ObiColliderBase collider = world.colliderHandles[contact.other].owner;
if (collider != null && collider.gameObject.tag == "VRHand")
{
Valve.VR.InteractionSystem.Hand hand = collider.gameObject.GetComponent<Valve.VR.InteractionSystem.Hand>();
// set that we are currently dragging
draggingHand = hand;
}
}
}
}
void DragMove(Valve.VR.InteractionSystem.Hand hand) {
Vector3 velocity;
Vector3 massagedVelocity;
Vector3 angularVelocity;
Vector3 currentPositon = hand.transform.position;
Valve.VR.InteractionSystem.GrabTypes startingGrabType = hand.GetGrabStarting();
if (velocityEstimator != null) {
velocityEstimator.BeginEstimatingVelocity();
}
velocity = hand.GetTrackedObjectVelocity(releaseVelocityTimeOffset);
angularVelocity = hand.GetTrackedObjectAngularVelocity(releaseVelocityTimeOffset);
massagedVelocity = -velocity / 25; //arbitrary
Valve.VR.InteractionSystem.GrabTypes bestGrabType = hand.GetBestGrabbingType();
if ( bestGrabType != Valve.VR.InteractionSystem.GrabTypes.None && hand.currentAttachedObject == null) {
hand.Hide();
m_CharacterController.Move(massagedVelocity);
}
// upon release grip, stop dragmove state
// TODO - unset when out of range (can't drag forever)
if ( bestGrabType == Valve.VR.InteractionSystem.GrabTypes.None ) {
hand.Show();
draggingHand = null;
};
}
}
A couple of notes:
-I tagged the VR hands with the tag "VRHand".
-I added a simple box collider with "trigger" set to true and Obi Collider to Valve's VR hands on the Player object.
-You have to pass in the player object and Obi Solver to the script. There's probably a better way of doing this. Like I said, this is an unpolished script!
-If you want to have this "grab" the rope particle instead of climbing it in a dragmove style, you could apply the velocity from the hands ("velocity" in the script) to the velocity of the currently grabbed rope particle (could be derived from "collider" in the script here, could create new top-level private variable "activeParticle" and set it when grabbed).
Just came to this forum for a completely unrelated reason and came across this thread. Coincidentally just solved this problem this week to build a grappling hook in the vanilla SteamVR 2.0 unity plugin. Proof:
The trick was getting steamVR to interact with the obi particles. Here's my ROUGH, unpolished code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using Obi;
using Valve.VR;
[RequireComponent(typeof(ObiSolver))]
public class RopeClimb : MonoBehaviour
{
public ObiSolver solver;
protected Valve.VR.InteractionSystem.VelocityEstimator velocityEstimator;
public GameObject Player;
public float releaseVelocityTimeOffset = -0.011f;
private CharacterController m_CharacterController;
private bool detectingCollisions = true;
private Valve.VR.InteractionSystem.Hand draggingHand = null;
void Start()
{
m_CharacterController = Player.GetComponent<CharacterController>();
}
void Update()
{
// subscribe to collision
if (detectingCollisions == true) {
solver.OnCollision += Solver_OnCollision;
detectingCollisions = false;
}
// only set upon successful collision + grip
if (draggingHand != null) {
DragMove(draggingHand);
}
}
void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
{
var world = ObiColliderWorld.GetInstance();
foreach (Oni.Contact contact in e.contacts)
{
// this one is an actual collision:
if (contact.distance < 0.01)
{
ObiColliderBase collider = world.colliderHandles[contact.other].owner;
if (collider != null && collider.gameObject.tag == "VRHand")
{
Valve.VR.InteractionSystem.Hand hand = collider.gameObject.GetComponent<Valve.VR.InteractionSystem.Hand>();
// set that we are currently dragging
draggingHand = hand;
}
}
}
}
void DragMove(Valve.VR.InteractionSystem.Hand hand) {
Vector3 velocity;
Vector3 massagedVelocity;
Vector3 angularVelocity;
Vector3 currentPositon = hand.transform.position;
Valve.VR.InteractionSystem.GrabTypes startingGrabType = hand.GetGrabStarting();
if (velocityEstimator != null) {
velocityEstimator.BeginEstimatingVelocity();
}
velocity = hand.GetTrackedObjectVelocity(releaseVelocityTimeOffset);
angularVelocity = hand.GetTrackedObjectAngularVelocity(releaseVelocityTimeOffset);
massagedVelocity = -velocity / 25; //arbitrary
Valve.VR.InteractionSystem.GrabTypes bestGrabType = hand.GetBestGrabbingType();
if ( bestGrabType != Valve.VR.InteractionSystem.GrabTypes.None && hand.currentAttachedObject == null) {
hand.Hide();
m_CharacterController.Move(massagedVelocity);
}
// upon release grip, stop dragmove state
// TODO - unset when out of range (can't drag forever)
if ( bestGrabType == Valve.VR.InteractionSystem.GrabTypes.None ) {
hand.Show();
draggingHand = null;
};
}
}
A couple of notes:
-I tagged the VR hands with the tag "VRHand".
-I added a simple box collider with "trigger" set to true and Obi Collider to Valve's VR hands on the Player object.
-You have to pass in the player object and Obi Solver to the script. There's probably a better way of doing this. Like I said, this is an unpolished script!
-If you want to have this "grab" the rope particle instead of climbing it in a dragmove style, you could apply the velocity from the hands ("velocity" in the script) to the velocity of the currently grabbed rope particle (could be derived from "collider" in the script here, could create new top-level private variable "activeParticle" and set it when grabbed).