Drag and rotate object similarly to Monument Valley rotation mechanics?

Hello everybody,

I’ve been trying to get an object to rotate just as the drag event works in Monument Valley. Here’s an example (skip to 0:13) youtube vid

Also if you happen to own Monument Valley, check Chapter 7 (“The Rookery”), that way you will instantly understand the type of rotation-movement I want to achieve.

So far I’ve tried a lot of things I found on other people’s questions & topics but just can’t get it to work right. Also I’m trying to get it work with the Void OnMouseDrag (). Asking for help here is literally the last thing I have left.

Not sure what else I should say regarding this, my so far Unity knowledge isn’t enough to figure this out by my own. Here’s also the code I last tried. If you feel like helping me then thank you in advance.

Edit: Google Drive link
did a quick project, try to rotate the object from bottom->Right->Top, it will stop halfway and then rotate backwards. If you constantly drag on the X axis it will keep rotating though which is also wrong. On MV, it works just fine when you do a full circle.

Hopefully the last edit: Here’s the final script Pastebin Link

using UnityEngine;
using System.Collections;
 
public class DragRotateX : MonoBehaviour
{
 
    public int speed;
    public float friction;
    public float xDeg;
    public float yDeg;
    public float zDeg;
    Quaternion fromRotation;
    Quaternion toRotation;
 
  void OnMouseDrag()
     {
          yDeg += Input.GetAxis ("Mouse Y") * speed * friction;
          xDeg -= Input.GetAxis ("Mouse X") * (Mathf.Cos (yDeg/60)*speed);
          transform.eulerAngles = new Vector3(yDeg,xDeg,zDeg);     
     }
  
}

Hey @PictonicSudio, I’d like to use your script but the math is beyond me, if I were to attempt to alter the axis that it operates on (i.e. to x or z) what would I change in this script? Furthermore, is it possible to make it work even when the object is viewed from the “bottom” (opposite side) without generating the rotation in opposite direction?

Try this script instead :slight_smile:

    private Quaternion originalRotation;
    private float startAngle = 0;

    public void Start()
    {
        originalRotation = this.transform.rotation;
    }
    public void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            MouseDown();
        }
        if (Input.GetMouseButton(0))
        {
            MouseHeld();
        }
    }

    public void MouseDown()
    {
        originalRotation = this.transform.rotation;
        Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position);
        Vector3 vector = Input.mousePosition - screenPos;
        startAngle = Mathf.Atan2(vector.y, vector.x) * Mathf.Rad2Deg;
    }

    public void MouseHeld()
    {
        Vector3 screenPos = Camera.main.WorldToScreenPoint(transform.position);
        Vector3 vector = Input.mousePosition - screenPos;
        float angle = Mathf.Atan2(vector.y, vector.x) * Mathf.Rad2Deg;
        Quaternion newRotation = Quaternion.AngleAxis(angle - startAngle, this.transform.up);
        newRotation.z = 0; 
        newRotation.eulerAngles = new Vector3(0, -newRotation.eulerAngles.y, 0);
        this.transform.rotation = originalRotation * (newRotation);
    }