- Home /
How do I rotate a 2D object based on it's velocity?
Hello everyone,
I am working on a 2D game and I am trying to get my character to rotate based on its velocity. An example of the effect that I am trying to get can be seen in this video: http://youtu.be/mYUzCq6G0AY?t=25s
Quaternions and rotation in general are a bit over my head, and trying to map rotation to the characters velocity makes it even more difficult. Can someone help me out?
Answer by robertbu · Sep 24, 2014 at 11:39 AM
The following code assumes that the front side of your sprite is pointing right when the rotation is (0,0,0).
function FixedUpdate() {
var dir = rigidbody2D.velocity;
var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
rigidbody2D.MoveRotation(angle);
}
No Quaternions involved :)
I dropped that code in and the sprite just alternates between pointing straight up (90 degrees) when moving up on the screen, and straight down (-90 degrees) when moving down on the screen. If I stop giving input, the sprite eventually points forward again.
Here is the code that I am using to control the player. I think that maybe the problem is here, but I don't know. Any help would be greatly appreciated.
void Update () {
// I'm using an on-screen UI slider to simulate the player sliding their finger up and down on the screen.
// The slider goes from 0.0f - 1.0f. I am setting it to 0.5f by default (center)
if (Input.Get$$anonymous$$ey("up") || sliderValue > 0.6f){
move = true;
force = new Vector2 (0.0f, moveForce * $$anonymous$$athf.Sign(sliderValue)); // moveForce is 20.0f
}
if (Input.Get$$anonymous$$ey("down") || sliderValue < 0.4f){
move = true;
force = new Vector2 (0.0f, -moveForce * $$anonymous$$athf.Sign(sliderValue));
}
print (sliderValue);
}
void FixedUpdate(){
if (move) {
if (fuel > 0.0f) {
rigidbody2D.AddForce(force);
}
move = false;
}
}
I tested the code above before I posted it. It assumes 1) it is the only thing impacting the rotation, that the ship is a sprite, and that the 'front' is facing right when the sprite's rotation is (0,0,0). If you want to put a package of your project (or an example project demonstrating the problem), on the net and provide a link, I'll download it and figure out what is going on.
The project files are located below. I am using Unity 4.6 beta 18 for the UI. If you aren't running 4.6 just let me know and I can package it back up without the UI element. Thank you very much for looking at this for me!
The rotation code I provided uses the velocity of the player to calculation the direction. I'm going to assume that you plan to keep the ship in one place on the 'x' axis and move the obstacles to the ship. If that is the case, then you need to add in the relative world velocity of the ship into 'dir' before doing the calculation. Here are some changes to your code to demonstrate. You'll need to adjust the 'worldVelocity' to match the rate at which obstacles move towards the player.
using UnityEngine;
using System.Collections;
public class Player : $$anonymous$$onoBehaviour {
float maxSpeedY = 10.0f;
Vector2 worldVelocity = Vector2.right * 2.5f;
void Start(){
Physics2D.gravity = new Vector2 (0.0f, 0.0f);
}
void FixedUpdate () {
var dir = rigidbody2D.velocity;
dir += worldVelocity;
var angle = $$anonymous$$athf.Atan2(dir.y, dir.x) * $$anonymous$$athf.Rad2Deg;
rigidbody2D.$$anonymous$$oveRotation(angle);
if ($$anonymous$$athf.Abs(rigidbody2D.velocity.y) >= maxSpeedY){
rigidbody2D.velocity = new Vector2(rigidbody2D.velocity.x, $$anonymous$$athf.Sign(rigidbody2D.velocity.y) * maxSpeedY);
}
}
}
That worked! Thank you so much! One other question, is there a way to limit how much the object rotates? For example, if I wanted to make sure that it never passes +45 or -45 degrees.