Rotate object with mouse cursor that slows down on release

Hi,

I am grabbing an object with the mouse cursor and rotating it, but when I release the mouse button I want it to continue to rotate a little then slow down to a stop.

I am doing the rotation in the OnMouseDrag function:

function OnMouseDrag () { RotationSpeed = 2; transform.Rotate (0, -RotationSpeed*Input.GetAxis ("Mouse X"), RotationSpeed*Input.GetAxis ("Mouse Y"), 0);

}

I have added a rigidbody component but that doesn't help. Do I need to calculate and apply a torque?

THANK YOU!

Try this. it's untested (I don't have Unity in front of me right now)

Ok, now implemented and tested, and turns out it was a little more complex to implement - mainly because at a high framerate, you get many frames where the mouse axis input is zero during a drag - so if you don't keep track of speed over a number of frames and you release the button during one of these 'zero value' frames, it appears as though the mouse wasn't moving!

First, the rotation is done in Update rather than MouseDrag, so that it can continue after the mouse is released. I'm using OnMouseDown to detect that this object was originally clicked on, and subsequently using Input.GetMouseButton to determine that the mouse is still held down.

Basically, while dragging, it keeps a separate "average speed" value (avgSpeed), which contains the current speed of rotation averaged over the last half-second or so (Using Lerp). It then uses this value when the mouse is released as the speed to continue rotating, and gradually Lerps this value down to zero to slow the rotation.

I have also used a different method of rotating the objects so that the rotation direction is always in accordance with the direction that you're dragging the mouse in screen-space.

Hope this fits what you're looking for!

var rotationSpeed = 10.0;
var lerpSpeed = 1.0;

private var speed = new Vector3();
private var avgSpeed = new Vector3();
private var dragging = false;
private var targetSpeedX = new Vector3();

function OnMouseDown() 
{
    dragging = true;
}

function Update () 
{

    if (Input.GetMouseButton(0) && dragging) {
        speed = new Vector3(-Input.GetAxis ("Mouse X"), Input.GetAxis("Mouse Y"), 0);
        avgSpeed = Vector3.Lerp(avgSpeed,speed,Time.deltaTime * 5);
    } else {
        if (dragging) {
            speed = avgSpeed;
            dragging = false;
        }
        var i = Time.deltaTime * lerpSpeed;
        speed = Vector3.Lerp( speed, Vector3.zero, i);   
    }

    transform.Rotate( Camera.main.transform.up * speed.x * rotationSpeed, Space.World );
    transform.Rotate( Camera.main.transform.right * speed.y * rotationSpeed, Space.World );

}

Thanks @duck, this saved me a lot of time. For the record here’s a translation to C#, hope it’s correct.

using UnityEngine;
using System.Collections;

public class DragRotateSlowDown : MonoBehaviour {

	private float rotationSpeed = 10.0F;
	private float lerpSpeed = 1.0F;

	private Vector3 theSpeed;
	private Vector3 avgSpeed;
	private bool isDragging = false;
	private Vector3 targetSpeedX;

	void OnMouseDown() {

		isDragging = true;
	}

    void Update() {

		if (Input.GetMouseButton(0) && isDragging) {
			theSpeed = new Vector3(-Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 0.0F);
			avgSpeed = Vector3.Lerp(avgSpeed, theSpeed, Time.deltaTime * 5);
		} else {
			if (isDragging) {
				theSpeed = avgSpeed;
				isDragging = false;
			}
			float i = Time.deltaTime * lerpSpeed;
			theSpeed = Vector3.Lerp(theSpeed, Vector3.zero, i);
		}

		transform.Rotate(Camera.main.transform.up * theSpeed.x * rotationSpeed, Space.World);
		transform.Rotate(Camera.main.transform.right * theSpeed.y * rotationSpeed, Space.World);
	}
}

Hello, seems like a great script, but I can’t understand how to make it work. Should I attach it to the object I want to rotate? If yes, it doesn’t seem to work with me.

Thank you in advance!

Following @stek very simple and very helpful example (on a different thread). I took his code and modified it so the can spin on both sides while accepting touch controls so it can work on mobile devices. Simply, attach the script to the spinning object. Bare with me, i am a beginner. The script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpinWheelScript : MonoBehaviour {

float pointerY;
float f_lastX = 0.0f;
float f_difX = 0.5f;
float f_steps = 0.0f;
int i_direction = 1;

void Start()
{
    pointerY = Input.GetAxis("Mouse Y");
}

void Update()
{

    if (Input.GetMouseButtonDown(0))
    {
        f_difX = 0.0f;
    }

    else if (Input.touchCount > 0)
    {
        pointerY = Input.touches[0].deltaPosition.y;
        f_difX = Mathf.Abs(f_lastX - pointerY);
        var touch = Input.GetTouch(0);

        if (touch.position.x > Screen.width / 2)
        {
            // Right
            if (f_lastX < Input.GetAxis("Mouse Y"))
            {
                i_direction = 1;
                transform.Rotate(Vector3.forward, f_difX * Time.deltaTime);
            }

            if (f_lastX > Input.GetAxis("Mouse Y"))
            {
                i_direction = -1;
                transform.Rotate(Vector3.forward, -f_difX * Time.deltaTime);
            }
        }
        else if (touch.position.x < Screen.width / 2)
        {
            // Left
            if (f_lastX < Input.GetAxis("Mouse Y"))
            {
                i_direction = -1;
                transform.Rotate(Vector3.forward, -f_difX * Time.deltaTime);
            }

            if (f_lastX > Input.GetAxis("Mouse Y"))
            {
                i_direction = 1;
                transform.Rotate(Vector3.forward, f_difX * Time.deltaTime);
            }
        }

        f_lastX = -pointerY;
        f_difX = 500f;
    Debug.Log(f_difX);
    }
    else
    {
        if (f_difX > 0.5f) f_difX -= 1f;
        if (f_difX < 0.5f) f_difX += 1f;

        transform.Rotate(Vector3.forward, f_difX * i_direction * Time.smoothDeltaTime);
    }
}
}

Currently, the object will spin based on a swipe along the Y axis, you can simple change it by replacing the Y’s with X’s. Also, i’ve modified the speeds to fit my liking. Hope this helps.

Cheers!