Help?!
I am trying to get an object to rotate appropriately based on the angle of the analog stick. I am facing an issue where the angle is outputting at very strict 0/90 degrees and only in the upper and right quadrants.
Once the angle is calculated properly, it is my intention to have rotation of my gun transform match. I believe I need a Quaternion for this.
This is for a simple 2D-plane game using the 3D toolset. Any advice would be greatly appreciated.
// ROTATE A GUN OBJECT AROUND THE Z-AXIS
// BASED ON THE ANGLE OF THE RIGHT ANALOG STICK
float x = Input.GetAxis ("R_analog_horz");
float y = Input.GetAxis ("R_analog_vert");
float aim_angle;
// CANCEL ALL INPUT BELOW THIS FLOAT
float R_analog_threshold = 0.30f;
if (x < Mathf.Abs (R_analog_threshold)) {
x=0.0f;
}
if (y < Mathf.Abs (R_analog_threshold)) {
y=0.0f;
}
// USED TO CHECK OUTPUT
Debug.Log(" horz: " + x + " vert: " + y);
// CALCULATE ANGLE AND ROTATE
if (x != 0.0f || y != 0.0f) {
aim_angle = Mathf.Atan2 (y, x) * Mathf.Rad2Deg;
// USED TO CHECK OUTPUT
Debug.Log ("angle: " + aim_angle);
// SIMPLE TEST TO CHECK IF OBJECT IS REFERENCED PROPERLY
// WILL BE REPLACED WITH A FUNCTIONING ROTATE WHEN ANGLE
// (AROUND Z-AXIS) IS FIGURED OUT
gun_test.transform.Rotate ( new Vector3(0, y, x) );
}
Your logic on lines 9 and 12 is wrong. It should be:
if (Mathf.Abs(x) < R_analog_threshold) {
x = 0.0f;
}
if (Mathf.Abs(y) < R_analog_threshold) {
y = 0.0f;
}
While it is probably okay, I never like direct comparisons between floats. So change line 20 to:
if (x >= R_analog_threshold || y >= R_analog_threshold) {
Transform.Rotate() is a relative rotation, so unless you reset the rotation each time the object is rotated, you want to do something else. If this is a 2D game, make sure the right side of your object is considered front when the rotation is (0,0,0), then do:
gun_test.transform.rotation = Quaternion.AngleAxis(aim_angle, Vector3.forward);
Thak you very much. For reference, the final code ended up being.
// ROTATE A GUN OBJECT AROUND THE Z-AXIS
// BASED ON THE ANGLE OF THE RIGHT ANALOG STICK
float x = Input.GetAxis ("R_analog_horz");
float y = Input.GetAxis ("R_analog_vert");
float aim_angle = 0.0f;
bool aiming_right = false;
bool aiming_up = false;
// USED TO CHECK OUTPUT
//Debug.Log(" horz: " + x + " vert: " + y);
// CANCEL ALL INPUT BELOW THIS FLOAT
float R_analog_threshold = 0.20f;
if (Mathf.Abs(x) < R_analog_threshold) {x = 0.0f;}
if (Mathf.Abs(y) < R_analog_threshold) {y = 0.0f;}
// CALCULATE ANGLE AND ROTATE
if (x != 0.0f || y != 0.0f) {
aim_angle = Mathf.Atan2(y, x) * Mathf.Rad2Deg;
// ANGLE GUN
gun_test.transform.rotation = Quaternion.AngleAxis(aim_angle, Vector3.forward);
}
The way you’re handling the threshold seems like it’d cause some jumpiness. It’s better to combine both axis.
float? getStickAngle()
{
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
float magnitudeish = Mathf.Abs(vertical) + Mathf.Abs(horizontal); // less intense than Vector2(horizontal, vertical).magnitude
if (magnitudeish < R_analog_threshold) // inside deadzone
return null;
return Mathf.Atan2(horizontal, -vertical) * Mathf.Rad2Deg;
}