![]() |
Help Grab Rope - VR - Printable Version +- Obi Official Forum (https://obi.virtualmethodstudio.com/forum) +-- Forum: Obi Users Category (https://obi.virtualmethodstudio.com/forum/forum-1.html) +--- Forum: Obi Rope (https://obi.virtualmethodstudio.com/forum/forum-4.html) +--- Thread: Help Grab Rope - VR (/thread-2422.html) |
RE: Grab Rope - VR - mo1ok - 18-02-2021 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). RE: Grab Rope - VR - Xanduffy - 19-02-2021 (18-02-2021, 04:16 AM)mo1ok Wrote: -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). As Jose pointed out to me early in this thread, I think it's better create a new pin constraint between the grabbed particle and the hand if you want the other rope constraints to factor in rather than allowing the rope to stretch infinitely by overriding the velocity directly. This is my understanding at least! Nice to see someone else working on a similar project! RE: Grab Rope - VR - tpaslou - 22-02-2021 I have tried to add many Obi Particle Attachments so I could grab each one of them instead of particles but there are some problems with this approach. There is a digression from the actual rope and when you grab one Particle and the velocity does not apply to the rest of them. Maybe I could make all other Rigid Bodies Kinematic apart from the one being grabbed. But probably working with particles directly instead of Particle Attachments is the right way. Although I still cant find a solution for the weird jitter and rotations when I attach my hand to particles. RE: Grab Rope - VR - josemendez - 22-02-2021 (22-02-2021, 12:11 PM)tpaslou Wrote: I have tried to add many Obi Particle Attachments so I could grab each one of them instead of particles but there are some problems with this approach. Dynamic particle attachments create pin constraints for individual particles under the hood, so it's exactly the same as you manually creating pin constraints, only more convoluted. Quote:There is a digression from the actual rope and when you grab one Particle the velocity does not apply to the rest of them. There should not be any digression if the attachment (or pin constraints) are properly set up: no pin constraints inside colliders, appropriate offset passed to the pin constraint, etc. Grabbing one particle will only set the velocity for that one particle, it can't possible affect other particles directly. The rest of particles will move as a result of distance/bend constraints in the rope. RE: Grab Rope - VR - josemendez - 22-02-2021 (19-02-2021, 09:35 PM)Xanduffy Wrote: As Jose pointed out to me early in this thread, I think it's better create a new pin constraint between the grabbed particle and the hand if you want the other rope constraints to factor in rather than allowing the rope to stretch infinitely by overriding the velocity directly. This is my understanding at least! 100% correct ![]() Directly setting the velocity or position of a particle only affects the particle, which means the object will act as if no rope was present at all. This is what static attachments do. When grabbing objects in VR, you want your hands to behave within the physical constraints of the VR environment, which means you don't want to be able to stretch a rope indefinitely (as you wouldn't be able to lift a very heavy object, put your hands inside a wall, etc). The rope should resist stretching once it's completely tense, by applying a force to your hand that opposes the pulling force. So you need dynamic attachments (or pin constraints, which is what dynamic attachments use internally) for this. RE: Grab Rope - VR - tpaslou - 23-02-2021 (22-02-2021, 12:21 PM)josemendez Wrote: Dynamic particle attachments create pin constraints for individual particles under the hood, so it's exactly the same as you manually creating pin constraints, only more convoluted. So I created a script which enables and disables Kinematic and Particle attachments based on the "node" grabbed. I want the kinematic nodes to follow the transform of the closest Particle. How can I achieve that via script ? RE: Grab Rope - VR - josemendez - 23-02-2021 (23-02-2021, 12:42 PM)tpaslou Wrote: So I created a script which enables and disables Kinematic and Particle attachments based on the "node" grabbed. I want the kinematic nodes to follow the transform of the closest Particle. How can I achieve that via script ? Should be pretty straightforward: iterate over all particle positions, find the closest one, and then set the kinematic object's position to that. See: http://obi.virtualmethodstudio.com/tutorials/scriptingparticles.html Obi exposes particle positions that you can iterate over, the rest of it is run of the mill code. Let me know if you have trouble calculating distances, finding the closest, etc. Edit: if the idea is to have one kinematic rigidbody per particle, and then use these for collision detection and grabbing, that's not a good one imho. Particles already perform collision detection and can be pinned to any position of a body, so this is just reinventing the wheel. Having a rigidbody per particle won't be very performant, either. A good solution is to iterate over contacts, find the one closest to the hand, and pin it (as Xanduffy's code does). RE: Grab Rope - VR - tpaslou - 24-02-2021 (23-02-2021, 12:45 PM)josemendez Wrote: Edit: if the idea is to have one kinematic rigidbody per particle, and then use these for collision detection and grabbing, that's not a good one imho. Particles already perform collision detection and can be pinned to any position of a body, so this is just reinventing the wheel. Having a rigidbody per particle won't be very performant, either. A good solution is to iterate over contacts, find the one closest to the hand, and pin it (as Xanduffy's code does). I have used that code but the rope behaves unexpectedly when grabbing. It rotates at the point of grab and this affects the whole rope RE: Grab Rope - VR - josemendez - 24-02-2021 (24-02-2021, 10:35 AM)tpaslou Wrote: I have used that code but the rope behaves unexpectedly when grabbing. It rotates at the point of grab and this affects the whole rope It shouldn't do that, it's just constraining the position of a particle. Can you share a video of this? RE: Grab Rope - VR - tpaslou - 24-02-2021 (24-02-2021, 10:39 AM)josemendez Wrote: It shouldn't do that, it's just constraining the position of a particle. Can you share a video of this? So this is the video : https://vimeo.com/516147132 The code that I used is : Code: using UnityEngine; |