- Home /
2D Rotate Object With Clamp Gradually. (C#)
Hello all, I've been looking all over Unity Answers for the answer to this but can't seem to find it, and the ones I do find don't seem to work or I just can't get my head around them.
So my problem is that I want to have my 2D character rotate left and right on the z axis when I move them up and down, but I need it to happen gradually over time, so it's not instant.
I also need my player to gradually revert back to looking straight ahead when the player isn't pressing any keys. I've tried this with else and else if statements but have had no luck.
Also tried a float with acceleration variable * Time.deltaTime but that didn't work out either.
Here is what I have so far:
using UnityEngine;
using System.Collections;
public class PlayerControl : MonoBehaviour {
public float horizontalSpeed = 9.0f;
public float horizontalDownSpeed = 3.0f;
public float gravitySpeed = 3.0f;
public float rotationSpeed = 20f;
void Update() {
if (Input.GetKey (KeyCode.UpArrow)) {
transform.position += Vector3.up * horizontalSpeed * Time.deltaTime;
rotationSpeed = Mathf.Clamp (rotationSpeed, 30, 30);
transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, rotationSpeed);
} else if (Input.GetKey (KeyCode.DownArrow)) {
transform.position += Vector3.down * horizontalDownSpeed * Time.deltaTime;
rotationSpeed = Mathf.Clamp (rotationSpeed, -30, 30);
transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x, transform.localEulerAngles.y, -rotationSpeed);
}
transform.position += Vector3.down * gravitySpeed * Time.deltaTime;
}
}
Any help is greatly appreciated! Thanks!
Answer by Mark Gossage · Jun 08, 2015 at 06:02 PM
I have written very similar code before for having my planes rotate side-side when the player moves. This should get you going.
public class PlayerMove : MonoBehaviour {
public float maxMove=0.1f; // speed of the movement of the object
public float maxTurn=30; // max angle it turns up/down
public float turnRate=10; // how quickly it turns up/down
Rigidbody2D rb2d;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D> ();
}
// Update is called once per frame
void Update () {
float delta = Input.GetAxis ("Vertical");
rb2d.MovePosition (rb2d.position + Vector2.up * delta * maxMove * Time.deltaTime);
// simply set the angle
//rb2d.rotation = turnAngle * delta;
// use Lerp to set the angle
rb2d.rotation = Mathf.Lerp (rb2d.rotation, maxTurn * delta, turnRate*Time.deltaTime);
// you could use SmoothStep/SmoothDamp as well
}
}
Thanks a lot $$anonymous$$ark, I really appreciate the answer!
Alright, so I've tried this, I had to put it into a seperate script to get it to work though, I can't work out how to put it inside of my if (Input.Get$$anonymous$$ey ($$anonymous$$eyCode.UpArrow)) { & down statements.
I will be using touch input later and I understand how to change them later when they're in Get$$anonymous$$ey statements, but I'm not comfortable with Axis'
Also, is it possible to not need a RigidBody2D? I have my own gravity anyway and I don't need RigidBody for anything else.
Sorry about the follow up questions, but I need to future-proof this for myself.
If you needed to switch to Get$$anonymous$$ey, here is how I would do it.
float delta=0;
if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.Up)) delta++;
if (Input.Get$$anonymous$$ey($$anonymous$$eyCode.Down)) delta--;
As for the RigidBody2D, you need it. I put the gravity multiplier at 0, because I didn't want gravity making this thing fall. Check the Unity tutorials for 2D, you need a RigidBody2D otherwise you will not get collision detection routines.
Oh wow, that worked a charm, thank you very much!
I have one more question while you're here though, do you know how I might have my player want to rotate slightly downwards due to the gravity? It looks weird having it dead straight.
Never$$anonymous$$d, I worked it out, just made some if else statements and made a new float called deltaGrav = 0; and a separate rotation function with that taken into account. Thanks for the help $$anonymous$$ark! I'm marking your answer as correct.
Does anybody happen to know why this solution has stopped working for me since upgrading to Unity 5 and on Windows 10?
Answer by LinkoVitch · Jun 09, 2015 at 03:29 AM
I think I had almost this exact problem yesterday! Hopefully my solution is of help to you.
I generate a Vector3 bodyLook which points in the direction I want my character to face (derived from joypad stick input). myBody is the actual GameObject of the entity I want to rotate. Then I use the following code to generate the rotation:
float a = Vector3.Angle(bodyLook, myBody.transform.forward );
float r = Vector3.Angle(bodyLook, myBody.transform.right);
float l = Vector3.Angle(bodyLook, myBody.transform.forward - myBody.transform.right );
if (a>0) {
float rate = a/turnDrag;
if (l>r) {
myBody.transform.Rotate (new Vector3(0f,rate,0f));
}else {
myBody.transform.Rotate (new Vector3(0f,-rate,0f));
}
}
turnDrag is a float that specifies an amount of drag on the rotation (think I find 10f works quite well, bigger = slower)
This works for me, hopefully this is of some help/use, really need to check that a is bigger than something other than 0, perhaps 0.1, otherwise you get a bit of a wobble when you get to your desired angle.
Thanks for the help Linko, I really appreciate it!
I've tried using your script, but I can't figure out what to call for above the updates (public floats etc) to make it work.
Any chance you know how to directly incorporate this method into my code above?