- Home /
How do I rotate an object at a constant rate a specific angle on key down?
I want to rotate an object 180 degrees (turn around) at a constant rate when either the 'A' or 'D' keys are pressed down to turn left or right respectively. This is the code that I want it to work with:
public float rotationSpeed = 50;
void Update() {
if (Input.GetKeyDown(KeyCode.A)) {
// Turn left 180 degrees at 50 degrees per second
}
if (Input.GetKeyDown(KeyCode.D)) {
// Turn left 180 degrees at 50 degrees per second
}
}
How would I go about implementing this?
With these kinds of problems, the limiting is usually the hard work. Does it have to be limited to 180 degrees? What axis are you rotating around? Are there other rotations on this object or do you start with the object axis aligned?
The game is a first person platformer. The object being rotated is the character that you are playing as (although it is just a box right now with a camera). The character is moving in what can effectivly be called a 2D space so the only movements are forwards, backwards, turn around, and jump. In short, yes it does have to be 180. The axis I want to rotate around is the y axis. There are no other rotations. It should only ever face 0 degrees rotation or 180 degrees on the y axis. Everything else should stay at 0.
Answer by robertbu · Feb 27, 2013 at 02:26 AM
Here is some rotation code. Note that RotateTowards() takes the shortest angle. When it is exactly 180 degrees, the direction is arbitrary. You can set the direction of rotation by an angle that is every so slightly more/less than 180 for your rotation. But it's going to turn forward and then turn back on the same path, it's not going to turn all the way around around. A few lines of code can change that.
@MickM approach will also work (and may be a bit more flexible) but I think there is a bug in his logic. It will quit rotating when the angle is >= 180, but nothing gets it back in bounds. Easy fix.
using UnityEngine;
using System.Collections;
public class Turn180 : MonoBehaviour {
public float speed = 50.0f;
private Quaternion qTo = Quaternion.identity;
private Quaternion qForward = Quaternion.identity;
private Quaternion qBack = Quaternion.Euler (0.0f, 180.0f, 0.0f);
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.A))
qTo = qBack;
else if (Input.GetKeyDown (KeyCode.D))
qTo = qForward;
transform.rotation = Quaternion.RotateTowards (transform.rotation, qTo, Time.deltaTime * speed);
}
}
So this works great, however I was hoping that the 'A' key would only turn 180 to the left no matter what direction you were facing and same for 'D' although to the right. Do you think that would be hard to implement?
I added logic so that it rotates as you specified. Note the added complexity of this code. This added complexity (in my $$anonymous$$d) is a good indication that @$$anonymous$$ick$$anonymous$$ 's solution would have been the better approach.
public class Turn180 : $$anonymous$$onoBehaviour {
public float speed = 50.0f;
private Quaternion qTo = Quaternion.identity;
private Quaternion qForward = Quaternion.identity;
private Quaternion qBack = Quaternion.Euler (0.0f, 180.0f, 0.0f);
private const float fLittleBit = 0.01f;
private bool bFirst = true;
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.D)) {
if (Vector3.Angle(transform.forward, Vector3.forward) < fLittleBit) {
transform.rotation = Quaternion.Euler(0.0f, 0.0f+fLittleBit, 0.0f);
qTo = qBack;
bFirst = true;
}
else if (Vector3.Angle(transform.forward, Vector3.back) < fLittleBit) {
transform.rotation = Quaternion.Euler(0.0f, 180.0f+fLittleBit,0.0f);
qTo = qForward;
bFirst = false;
}
else {
if (bFirst)
qTo = qBack;
else
qTo = qForward;
}
}
else if (Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.A)) {
if (Vector3.Angle(transform.forward, Vector3.forward) < fLittleBit) {
transform.rotation = Quaternion.Euler(0.0f, 0.0f-fLittleBit, 0.0f);
qTo = qBack;
bFirst = false;
}
else if (Vector3.Angle(transform.forward, Vector3.back) < fLittleBit) {
transform.rotation = Quaternion.Euler(0.0f, 180.0f-fLittleBit,0.0f);
qTo = qForward;
bFirst = true;
}
else {
if (bFirst)
qTo = qForward;
else
qTo = qBack;
}
}
transform.rotation = Quaternion.RotateTowards (transform.rotation, qTo, Time.deltaTime * speed);
}
}
This worked perfectly! Thank you for the help. I also added a few lines to anchor the object to the x axis so when moving while turning you wouldn't move off center.
Yea definitely a big bug there with getting stuck at the 180!
Easy fix for that is ins$$anonymous$$d of
if ((rotationTracker > -180)&&(rotationTracker < 180))
Use
if (( (rotationTracker + Time.deltaTime*rotation$$anonymous$$odifier) > -180) && ( (rotationTracker + Time.deltaTime*rotation$$anonymous$$odifier) < 180) )
Will just prevent rotation if it will go outside bounds of 180 degrees. This will not ever (normally) get to 180 degrees fully but will get quite close (around the 179 degree mark)
Really depends what you want... that way is just quick and simple. (Haha definitely dont use my initial answer though - it WILL get you stuck!!!)
Answer by MickM · Feb 27, 2013 at 01:59 AM
If you want it to stop at 180... Quick and dirty idea for you: Note - this is done quickly on iPad so you will have to actually put the below into code and test BUT it should do what you need!
rotationTracker = 0
rotationModifier = 1
Function update()
If keycode.a
rotationModifier =1
If keycode.d
rotationModifier =-1
if (rotationTracker>-180)&&(rotationTracker<180)
rotationTracker += Time.deltaTime x rotationModifier
transform.Rotate(0, rotationModiferx50xTime.deltaTime, 0)
Answer by sjurick · Aug 20, 2013 at 11:36 PM
I have an object that I want to rotate left, right, forward and backward using the arrow keys. It works, but my beta testers are saying the motion is too linear and want to be able to control the amount of rotation more.
I thought of doing something like adding exponential interpolation or Quaternion, but don't know how to implement it.
What I want to happen is have it to where when an arrow key is pressed, the object starts rotating in that direction, but slowly at first, then exponentially getting faster the longer its held down.
My code so far:
public class Tilt : MonoBehaviour {
public int tiltSpeed = 1;
void FixedUpdate () {
if(Input.GetButton("Tilt Forwards")) {
transform.Rotate(tiltSpeed * 1,0,0);
Debug.Log("Up Arrow Key Pressed!");
}
if(Input.GetButton("Tilt Backwards")) {
transform.Rotate(tiltSpeed * -1,0,0);
Debug.Log("Down Arrow Key Pressed!");
}
if(Input.GetButton("Tilt Left")) {
transform.Rotate(0,0,tiltSpeed);
Debug.Log("Left Arrow Key Pressed!");
}
if(Input.GetButton("Tilt Right")) {
transform.Rotate(0,0,tiltSpeed * -1);
Debug.Log("Right Arrow Key Pressed!");
}
}
}
sjurick - this needs to be opened as a new question, not posted as an 'answer' to an existing question. I'll be deleting it shortly.
Your answer
Follow this Question
Related Questions
Problems caused by non-unique Euler angle solutions 1 Answer
Restricting rotation to multiples of 15? 1 Answer
How do I apply rotations to parent child using Rigidbody? 0 Answers
90 Degree stopping rotation on y-axis issue 0 Answers
How can I fix this randomly rotating gun to an unknown degrees? 1 Answer