# Physics/Input Questions

Hi All,

I’m trying to set a scene up where the user can rotate/spin the object (by selecting the object with the left mouse button around with an organic-type feel ). Meaning if the user selects an object and moves the mouse quickly, then the object spins faster and takes longer to slow down.

Can someone point me in the right direction for this? I looked through the forums and scripting reference to no avail. much appreciated.

I was working on the same thing a while ago and it still feels a bit rough, although it basically works.

Here is a link to a webplayer demo:
http://www.grayboxgames.com/GBG/Tests/GrabNRotate.html

Have a look at this script to see how it works and then i would be happy to answer any questions. It needs to be attached to an object with a sphere collider. Number Averages can be tweaked to make the rotation continue more naturally after releasing the mouse button.

``````var numberAverages : int = 3;

private var originalRotation : Quaternion;
private var offsetRotation : Quaternion;

// Make sure there is always a Rigidbody
@script RequireComponent (Rigidbody)
@script RequireComponent (SphereCollider)

function Awake () {

numberAverages = Mathf.Clamp (numberAverages, 1, numberAverages);

}

function OnMouseDown () {
var hit : RaycastHit;
var dir : Vector3;

// Stop spinning
rigidbody.angularVelocity = Vector3.zero;

// Record initial variables
if (Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit)) {
originalRotation = transform.rotation;
dir = hit.point - transform.position;
offsetRotation = Quaternion.Inverse (Quaternion.LookRotation (dir));
Spin (dir);
}
}

function Spin (dir : Vector3) {
var hit : RaycastHit;
var previousDirList : Array = new Array ();
var currentDir : Vector3;

// Initialize previous dir list
for (var i : int = 0; i < numberAverages; i++) {
}

currentDir = dir;

// Make the object rotate with the cursor while we are grabbing it
while (Input.GetButton ("Fire1")  Physics.Raycast (camera.main.ScreenPointToRay(Input.mousePosition), hit)) {
// Remove first element of the array
previousDirList.RemoveAt (0);
// Add current dir to the end
currentDir = hit.point - transform.position;
transform.rotation =  Quaternion.LookRotation (currentDir) * offsetRotation * originalRotation;
yield;
}

// User let go of the mouse so make the object spin on its own
var avgPreviousDir : Vector3 = Vector3.zero;
for (dir in previousDirList) {
avgPreviousDir += dir;
}
avgPreviousDir /= numberAverages;
Kick (currentDir, avgPreviousDir);
}

function Kick (r2 : Vector3, r1 : Vector3) {
var linearVelocity : Vector3;
var angVelocity : Vector3;

// Calculate the angular velocity:  omega = r x v / r^2
linearVelocity = (r2 - r1) / Time.deltaTime;
rigidbody.angularVelocity = Vector3.Cross (r2, linearVelocity) / r2.sqrMagnitude;

}
``````

-Dan

Oh my! This is really great and is going to work out well. Thanks!

Couple of questions:

1. I have 4 sliders in my scene. Three control the X,Y and Z position of the object relative to the camera. one controls the FOV settings of the camera.

If I change the FOV settings so the object is “larger” in the viewport, then the sphere collider gets larger as well. This then changes the “physics” of the rotation of the object by the user. Meaning if the object is larger, then the same “click and drag” will move the object at a noticeable slower rate. Is there a way to dynamically set the radius of the sphere collider so that as the FOV increases or decreases, so does the radius?

1. Is there a way to set a clamp (i think this is the right teminology) to the rotation of a specific axis? Meaning can this be modified so the user can only rotate something 90 degrees in one axis but spin the object freely in the other axes?

Thanks again so much for the script

danny

You’re welcome

The script rotates the sphere so that the point on the sphere that was under the cursor when the mouse was clicked remains directly under the cursor until the user releases the mouse button. FOV doesn’t change this. On the other hand, if you want to make the rotation proportional to mouse delta movements, which is what i think you are after, then the whole script would be different.

Clamping the rotation could be done the way the MouseLook script found in the Standard Assets folder does it, so my script could be modified to clamp the angle.

thanks much for the info. I’ll try tweaking things so the clamp function works as well.
thanks again for the help,
daniel

Hello, sorry to bump in but this a very cool thread, very helpful, thx very much for sharing such a nice example and giving the code with very nicely commented lines.
You guys in Wisconsin rock!
THX a bunch!

Hi there!
I have a question for DannyJ.
I am quite new to Unity and interactive 3D programming, coming from the animation/modelling end of the field. It was great finding your grabNRotate script, that more or less achieved half of what I want to do. Many thanks! Next step would be to have clickable hotspots on the surface of the object. Imagine for example a mobile phone that you can spin around in space, and be able to interact with the buttons. How would I go about doing this?
I have tried adding child objects (cubes) with simple test scripts attached to them (for example switching a colour on mouseDown), but they become inactive when parented to the main object (the sphere), and furthermore they inherit the grabNRotate behavior instead.
I know, I am very much a programming newbie, so please bear with me. Maybe there is something basic that I have missed.

Cheers,
Mats

Did you update your GrabNRotate script? It’s exactly what I was looking for!

Great Script !!!

I Desperately need a very similar script for my 2d Disc. How simple would it be to convert this script to rotate a 2d disc like a wheel?

Any Suggestions welcomed !

It is possible to modify the script to get the object only rotates in horizontal axys?

Thanks.

Since it’s a rigidbody object, the easiest way to limit rotation to one axis is to add a hinge joint to it.

Could you please update us on how we could make it rotate only on horizontal axis by editing the rotate script?

Many thanks for the insight… too bad the script doesn’t work on Android devices…

Tried and failed… anybody knows why?

thanks buddy its a great script i tried it, and works perfect, I tried to move it only in horizontal direction but it works little bit wired …
let me try more.

Anyone have a thought on how to add to this script…

I need to be able to use player input to gradually build up the rotation speed of an object. So to get the object moving fast, the player would have to swipe many times in the same direction. If the player started swiping in the opposite direction of the current spin, it would take a while to slow down, and then build back up in the other direction.

I think the term some of you folks are looking for are constraints (clamps are for textures), and you can set that in the rigidbody, as noted… Here’s where there’s scripting info on it: