I’m making a 2D game with a top-down camera perspective (think classic asteroids game), and I wrote this code to control the player movement.
It seems like a lot of manual work for a rather simple problem. Is there any simpler way to do this? I would have thought that for sure there are probably simple ways to do this provided by Unity, but haven’t found anything myself. Is there any?
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float m_maxVelocity;
[SerializeField] private float m_force; //to apply forward movement
[SerializeField] private float m_rotateSpeed;
//to indicate rotation direction
//unity's z rotation seems to be anti-clockwise
private int m_left = 1;
private int m_right = -1;
private Vector3 m_spinAxis = new Vector3 (0, 0, 1f); //spin around z axis
private float m_zRotation; //to keep object's z rotation from transform
private float m_x; //for direction vector x component
private float m_y; //for direction vector y component
private float m_angle; //to keep angle of triangle when calculating vector
private Vector2 m_direction; //vector to keep direction to apply force when moving
private Animator anim;
void Start()
{
anim = GetComponent<Animator>();
}
//no need for Time.deltaTime in FixedUpdate()
void FixedUpdate()
{
bool up = Input.GetKey("up");
bool right = Input.GetKey("right");
bool left = Input.GetKey("left");
bool space = Input.GetKey("space");
if(up)
{
anim.SetFloat("speed", 1); //set animation to "move"
//if total speed does not exceed max, move.
if((rigidbody2D.velocity.x + rigidbody2D.velocity.y) < m_maxVelocity)
{Move();}
}
else {anim.SetFloat("speed", 0);} //when not moving, set animation to "idle"
if(left) {Rotate(m_left);}
if(right) {Rotate(m_right);}
m_zRotation = transform.rotation.eulerAngles.z;
}
void Rotate(int p_direction)
{
transform.Rotate(m_spinAxis, m_rotateSpeed * p_direction);
}
void Move()
{
//calc direction vector
m_direction = GetVector(m_zRotation);
//then add force
rigidbody2D.AddForce(m_direction * m_force);
}
Vector2 GetVector(float p_zRotation)
{
//find which quadrant we are in to calculate angle of triangle
//quadrants go anti-clockwise
if(p_zRotation > 0 p_zRotation < 90) //we are in first quadrant, angle is 90 - rotation
{
m_angle = 90f - p_zRotation;
//find x and y components for direction vector
m_x = CAH(m_angle, -1); //in first quadrant, x is negative
m_y = SOH(m_angle);
}
else if(p_zRotation > 90 p_zRotation < 180) //we are in the second quadrant, angle is rotation - 90
{
m_angle = p_zRotation - 90f;
m_x = CAH(m_angle, -1); //in second quadrant, x is negative
m_y = SOH(m_angle, -1); //in second quadrant, y is negative
}
else if(p_zRotation > 180 p_zRotation < 270) //we are in the third quadrant, angle is 270 - rotation
{
m_angle = 270f - p_zRotation;
m_x = CAH(m_angle);
m_y = SOH(m_angle, -1); //in third quadrant, y is negative
}
else if(p_zRotation > 270 p_zRotation < 360) //we are in the fourth quadrant, angle is rotation - 270
{
m_angle = p_zRotation - 270f;
m_x = CAH(m_angle);
m_y = SOH(m_angle);
}
else //angle is 0 degrees, we are moving straight up
{
m_x = 0f;
m_y = 1f;
}
return new Vector2(m_x, m_y);
}
float CAH(float p_angle, int p_sign = 1)
{
p_angle = ToRad(p_angle); //convert to rad because Mathf.Cos is in rad
return (Mathf.Cos(p_angle)) * p_sign;
}
float SOH(float p_angle, int p_sign = 1)
{
p_angle = ToRad(p_angle); //convert to rad because Mathf.Sin is in rad
return (Mathf.Sin(p_angle)) * p_sign;
}
float ToRad(float p_angle)
{
return ((Mathf.PI / 180f) * p_angle);
}
}
This works fine, just the way I want it, but since I’m new to programming I want to learn to find the simplest of solutions to simple problems and this doesn’t seem to be it, so I would appreciate any advice from someone more experienced.
Edit:
I forgot to articulate the actual “simple” problem that I’m trying to solve! The problem is that I need a direction vector to apply force. Since the player object can be rotated around the z axis, this force needs to be applied in the same direction as where the player object is facing.