Hi there, I will try to be as specific as possible.
I am developing a 2D sidescrolling game with sprites (2DToolkit), and I am stucked with this issue. First of all I need to make clear one thing: in order to change the sprite’s transform without affecting the controls, I am storing it under a different game object which is child to the player main object.
Now, when I have my character swimming, I can make him dive so the player can control him with fully 360º freedom. I am trying to do something as in Rayman Origins, I want the sprite to rotate towards the player direction: when my character is diving down, I want the sprite to rotate and face the bottom of the screen, when he turns left I want the sprite to rotate and face left… and so on.
Is there any way to convert player input to an angle or rotation value? Or a way to compare both things? For now, what I have is this:
var playerAngle : float = 0.0;
for (var child : Transform in transform)
{
playerAngle += Input.GetAxis("Horizontal") * rotationSpeed * Time.deltaTime;
//When Input
child.transform.Rotate(Vector3(0, 0, 1) * playerAngle);
}
But that is a very, very simple and rough code. I want the rotation of the sprite to stop when it matches the Player direction. Is there any quick way to do this or must I try it differently?
By the way, Input comes via WASD.
Thanks for your time.
One way to convert player input to Angle would be to calculate the Angle between the input vector and the forward direction for instance.
This is a crude example and hopefully enough to point you in the right direction.
void Update()
{
Vector3 moveVector = Vector3.zero;
moveVector.x = Input.GetAxis("Horizontal");
moveVector.y = Input.GetAxis("Vertical");
float angle = Vector3.Angle(moveVector, Vector3.right);
Vector3 cross = Vector3.Cross(moveVector, Vector3.right).normalized;
Debug.DrawLine(Vector3.zero, moveVector, Color.green);
Debug.DrawLine(Vector3.zero, cross, Color.red);
Debug.Log("Vector3 Angle:" + angle + " Cross (Z):" + cross.z + " Angle:" + angle * -cross.z);
}
debug.logs and debug.draw are there to help visualize those vectors.
Because Angle is 90 when up or down as opposed to 90 up and -90 down, I take the cross product which returns a vector that is perpendicular (z direction) to the input and right vector. The Z component of that vector (positive or negative) allows you to know if we are up or down.
Instead of normalizing this cross product, I could have instead used Mathf.sign to just get the positive or negative sign of the cross product which would have been more efficient then normalizing a vector.
Anyway, I hope this helps.
@Stephan_B Hey! I kind of made it work, thank you very much. In case you’re interested on it, here’s my current code:
//======================Diving===========================
if(diving)
{
gravity = 0.0;
moveDirection = Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetKey(KeyCode.RightArrow) !facingRight)
{
script = gameObject.GetComponentInChildren(tk2dSprite);
script.FlipX();
facingRight = true;
}
else if (Input.GetKey(KeyCode.LeftArrow) facingRight)
{
script = gameObject.GetComponentInChildren(tk2dSprite);
script.FlipX();
facingRight = false;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
if(!facingRight)
{
script = gameObject.GetComponentInChildren(tk2dSprite);
script.FlipX();
script.FlipY();
upsideDown = true;
facingRight = true;
}
}
else if (Input.GetKey(KeyCode.UpArrow))
{
if(!facingRight)
{
script = gameObject.GetComponentInChildren(tk2dSprite);
script.FlipX();
script.FlipY();
upsideDown = true;
facingRight = true;
}
}
if(Input.GetKey(KeyCode.LeftArrow) upsideDown)
{
script.FlipY();
upsideDown = false;
}
else if(Input.GetKey(KeyCode.RightArrow) upsideDown)
{
script.FlipY();
upsideDown = false;
}
if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow))
{
for (var child : Transform in transform)
{
var moveVector = Vector3.zero;
moveVector.x = Input.GetAxis("Horizontal");
moveVector.y = Input.GetAxis("Vertical");
if(Input.GetKey(KeyCode.LeftArrow))
{
moveVector.x = -Input.GetAxis("Horizontal");
moveVector.y = -Input.GetAxis("Vertical");
}
var angle = Vector3.Angle(moveVector, Vector3.right);
var cross = Vector3.Cross(moveVector, Vector3.right).normalized;
child.transform.rotation = Quaternion.Euler(Vector3(0, 0, angle * -cross.z));
}
}
}
Now I just have some weird issues to solve involving the sprite (it makes odd Flips sometimes, but I think I just messed it up with excessive “facingRight” and “upsideDown” coding).
Anyway, the rotation of the sprite works fine. Thx!