Good afternoon, everyone!
I’m trying to get my head wrapped around Quaternions and local object rotations, and I seem to be running into a bit of trouble getting a turret to work via the LookRotation and LookAt functions.
Currently, I’m just using primitives in Unity. I’m trying to stay away from the modeling end of things until I have the rules of combat worked out. Thus, it is just cubes and cylinders right now. The turret root is an empty object that is fixed to the ship and will turn and rotate with her. The turret root is essentially an anchor that will hold all the information regarding turret rotation and elevation limits. Attached to that is a box that serves as the turret ‘base’ that will rotate between those limits according to the heading of a given target object.
I’ve been able to establish a target for my turret and, using Vector3.Angles, I’ve been able to return seperate angles for the turret base and the turret root. However, these angle returns are based on the overall angle in 3d space. I’m unsure how to return seperate rotations for the local x y and z rotations. This is where I run into the problem, as I think I would need these to determine how the turret should turn and take aim.
You see, I’ve been able to use the following code to make the base object look toward it, but that base object also rotates up to to so. This is particularly troublesome when only the barrels are meant to handle the elevation. It also looks horrible!
I have two lines that I’ve been fiddling with and neither one works particularly well. The first Quaternion.Slerp uses the local rotation, but it tends to go a little wierd when the TargetRotation.z and .x = 0 lines are active. When I uncomment the baseTargetRotation.z and .x = 0 lines, it does lock the turret to the horizontal axis - until you rotate the root object. At that time, it tends to start spinning in a direction opposite to the x or z value that has been entered. Very wierd. It must be why we don’t change the .x or .z values unless we know what we’re doing. Very clearly, I don’t.
The second Slerp line is set to use the standard rotation, rather than localRotation. My understanding is that this is related to the world coordinates. I don’t get a spinning top anymore, but uncommenting the .z and .x = 0 lines does cause it to slowly level out according to the world coordinates - even if the base object is rotated over on her side. This makes sense, since that’s the world y axis, but it still isn’t what I’m looking for.
Anyhow, without further delay, here is the code in the present format. It’s applied to the turret root object, to which the base object is a child, and where the turret base and target objects are then assigned. If anyone has any suggestions, or perhaps an easier way to go about making this turret move, please let me know. All this talk of Slerps is making me thirsty, though. I’m off to snag a slurpee!
using UnityEngine;
using System.Collections;
public class LargeTurret : MonoBehaviour {
public Transform target; //target object
public GameObject turretBase; //turret base object. Will handle horizontal angles for aim.
//local angles for the turret root. Used to determine how far a turret may turn and elevate compared to the root object.
public int turretMaxAngle = 135;
public int turretMinAngle = -135;
public int turretMaxElevation = 50;
public int turretMinElevation = -10;
//how fast the turret may turn.
public float turretDegreesPerSecond = 0.02f;
private Transform myTransform; //this is the turret root object
private Transform baseTransform; //this is the turret base object
void Awake(){
myTransform = transform;
baseTransform = turretBase.transform;
}
void Update () {
//we will check distances and max/min angles after the rotation behaves itself.
//Initial target rotation data for the turret base object
Quaternion baseTargetRotation = Quaternion.LookRotation(target.position - baseTransform.position);
//zero base object on z and x rotations for the above variable.
//baseTargetRotation.x = 0;
//baseTargetRotation.z = 0;
//local rotation line. Causes spinning when parent object rotates out of 0,0,0 angle.
//baseTransform.rotation = Quaternion.Slerp(baseTransform.localRotation, baseTargetRotation, turretDegreesPerSecond * Time.deltaTime);
//world rotation line. Causes turret to become level with world y axis, but at least the turret doesn't turn into a top!
baseTransform.rotation = Quaternion.Slerp(baseTransform.rotation, baseTargetRotation, turretDegreesPerSecond * Time.deltaTime);
//Turret root and base rotation information. Angles to target.
Vector3 targetDir = target.position - transform.position; //turret root target direction
Vector3 baseTargetDir = target.position - baseTransform.position; //turret base target direction
Vector3 baseForward = baseTransform.forward; //turret base facing
Vector3 forward = transform.forward; //turret root facing
//DEBUG code. To be removed later.
Debug.DrawLine(target.transform.position, myTransform.position, Color.yellow);
Debug.Log("Target Angle from Bearing: " + Vector3.Angle(targetDir, forward));
Debug.Log("Target Angle from Base: " + Vector3.Angle(baseTargetDir, baseForward));
}
}