Search code examples
unity-game-enginevirtual-realityoculusquestunity-xr

Unity XR - Rotate a grabbed object with XRGrabInteractable around its pivot


I'm pretty new to VR development with Unity, what I need to do is to grab a clockwork object and rotate it around its pivot by moving the right hand controller, like if I had to do that in real life

Here's the scenario:

enter image description here

Here's the code I'm using in Update:

public class Box1: MonoBehaviour { 
    public Transform rightHandTransf;
    Vector3 handPosition; 

   
  void Update(){ 
     Vector3 rhPos = rightHandTransf.position; 
     Quaternion rhRot = rightHandTransf.rotation; 

     // clockworkM Rotation 
     rhPos.z = clockworkM.transform.position.z - Camera.main.transform.position.z; 
     handPosition = Camera.main.WorldToScreenPoint(rhPos); 
     clockworkM.transform.rotation = Quaternion.LookRotation(Vector3.back, handPosition - clockworkM.transform.position);
  }

}

What I get is that wherever I move the hand, the clockwork rotates just a little bit, and if I rotate the headset, the clockwork rotates based on my X axis rotation with my headset

Weird behavior, I have no idea what I'm doing wrong :(


Solution

  • you probably solved it by now but in case someone else stumbles on this. My solution is just for rotating object around Y axis but can be easily edited for any other direction:

    public Transform interactorTransform;
    float lastFrameAngle;
    public float multiplier = 1;
    
    private void Start() {
        XRGrabInteractable interactble = GetComponent<XRGrabInteractable>();
        interactble.selectEntered.AddListener(Selected);
        interactble.selectExited.AddListener(Deselected);
    }
    
    private void FixedUpdate() {
        if (interactorTransform != null) {
            float angle = Vector3.SignedAngle(interactorTransform.position - transform.position, interactorTransform.forward, Vector3.up);
            float delta = angle - lastFrameAngle;
            transform.Rotate(transform.up, delta*multiplier);           
            lastFrameAngle = angle;
        }
    }
    
    public void Selected(SelectEnterEventArgs arguments) {        
        interactorTransform = arguments.interactorObject.transform;
        lastFrameAngle = Vector3.SignedAngle(interactorTransform.position - transform.position, interactorTransform.forward, Vector3.up);        
    }
    
    public void Deselected(SelectExitEventArgs arguments) {        
        interactorTransform = null;        
    }