- Home /
This can't be impossible or? Rotate (flip) smoothly from one point to endpoint on mouseclick.
I've tried to follow all examples in the script references, about Quaternion, euler.angles, lerp and slerp, transform.Rotate vs transform.rotation, but can't get the effect I want. I can get a cube to spin around it's axis, I can get it to rotate smoothly under update (in several ways), but as soon as I try to connect that movement to a mouse click, it fails. The movement halts before the endpoint or flicker.
I don't know if it's related to Time.deltatime or Update or what.
This is what I want, example: On a Rayhit or Mouseclick; A flat Cube flipping over from, say 0 to 90 degrees on one axis, and with just some smoothness in the movement.
These two alternative codes both do some of the job but not completely:
The motion/animation is right in this code if I just put it under Update: { transform.rotation=Quaternion.identity;transform.rotation = Quaternion.Slerp(Startpoint.rotation, Endpoint.rotation, Time.time * speed); } (The variables startpoint and endpoint are set as public transforms and start is 0,0,0 in rotation and endpoint as 0,0,90)
This code gets the position and clicking right, but I can't get any smoothness/animation here, it will move instantly of course.
void OnMouseDown() { transform.Rotate(new Vector3(0,0,90)); } I tried to adjust my codes to some tips from links and tutorials, even setting a division sign before time.deltatime, (one link I suspect is related is this http://answers.unity3d.com/questions/200115/why-is-my-camera-shaky-in-editor-but-not-in-compil.html), I tried using Quaternions, euler.angles, defining variables and functions to try to get it right, just no luck.
Answer by giano574 · Mar 06, 2014 at 07:49 PM
You can use Quaternion.RotateTowards. Have a boolean set to true when the mouse is clicked and then use the function in the Update method:
if (rotate == true)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.eulerAngles(0,0,90),
speed * Time.deltaTime);
}
The RotateTorwards function will return a Quaternion that is speed * Time.deltaTime closer to the target rotation. As stated in the script reference the rotation will not overshoot.
See: https://docs.unity3d.com/Documentation/ScriptReference/Quaternion.RotateTowards.html
Thank you so much, I finally got it working! It rotates so nice! I recognize that rotateTowards vaguely, must have been too tired to pay properly attention to it. I managed now when making mouseclick turn a bool to true. (I added sort of "not true" factor also in the statement so the Update don't need to check all the time (but that's what update do but you know what I mean) perhaps one need that in some cases.
if (rotate== true && transform.rotation!= Endpoint.rotation) { transform.rotation = Quaternion.RotateTowards(transform.rotation, Endpoint.rotation, step); Debug.Log("if rotate is true"); }
Answer by fifthknotch · Mar 06, 2014 at 06:27 PM
Under the Update function in your first script add the if statement
if (Input.GetMouse(0) {
//rest of code
}
"it will move instantly of course." OnMouseDown only happens the frame the mouse button was clicked. It is not continuous. In your code, you tell the object to rotate 90 degrees instantly, that is why your rotation is correct but animation is not. Use instead OnMouse. It will happen every frame the mouse is down.
Good to know, thanks! At least now I can make the cube spin around (forever) by holding the mouse down, on the script with transform.Rotate. However with the other script, I still can't make it slow down in movement, I tried to tweak the speed float, and/or change the time type, it either stops before the endpoint or just moves instantly. And I would like to accomplish this with just one mouseclick, that is, click on the object, and it flips to the new position in a second or so. Perhaps I need to turn to an true animation solution here?
After whatching this tutorial (even though it's java, http://www.youtube.com/watch?v=kvgm0QBtZJw) I got it a little more right, by removing my original float and time.time or time.deltatime, put the float time += in ins$$anonymous$$d (and added as a variable at the beginning). Now it moves nice when holding down the mouse. But as I said I would like to accomplish it with just one $$anonymous$$ouseclick. Perhaps I can convert it to a function in some way...
void Update() { time += 0.01F; if (Input.Get$$anonymous$$ouseButton(0))
{
transform.rotation=Quaternion.identity;transform.rotation = Quaternion.Slerp(Startpoint.rotation, Endpoint.rotation, time);
}
Aw I did not realize you wanted it in one click. Yes giano's method is best.
Answer by robertbu · Mar 06, 2014 at 09:34 PM
Here is a bit of example code. It rotates the cube around the world 'y' axis. Each time it is clicked, it adds 90 degrees to the rotation. If you want eased movement at the end, change RotateTowards() to Slerp() and reduce the value of 'speed' in the Inspector.
#pragma strict
var qTo : Quaternion;
var speed = 45.0;
function Start() {
qTo = transform.rotation;
}
function Update() {
transform.rotation = Quaternion.RotateTowards(transform.rotation, qTo, Time.deltaTime * speed);
}
function OnMouseDown() {
qTo = Quaternion.AngleAxis(90.0, Vector3.up) * qTo;
}
When used with RotateTowards(), 'speed' is degrees per second.
Thanks! This alternative is also good. I did not know about this AngleAxis, this ter$$anonymous$$ology with Quaternions, Eulers and all can really be tough to know when and how to apply. (I can't upvote these answers yet, I'm too new, and it also seems like you can only mark one as answer, but I think they both give good working alternatives.)