I am trying to make an enemy turn to face my character on the Y axis and make the arms move on the X axis so that the guns on the end of the arms are pointing at me.
The the arms are a seperate object but are atteached to the enemy so if it turns so do they.
I have both sets of rotations working properly but if I have both running at the same time then it starts affecting the arm’s Y axis even though the code explicitly removes any Y axis movement from the arms. The only Y rotation should come directly from the enemy but that shouldn’t show in the arm’s rotation in the inspector and in this it is changes even though the slerp fuction should be moving it between 0 and 0 on the Y and Z axes.
This is the code now:
var arms:GameObject;
var leftGun:GameObject;
var rightGun:GameObject;
var bullet:GameObject;
private var lastKnownPlayerLocation:Transform;
private var currentAimAngle:float;
function Update () {
aim();
}
function aim(){
var newRotation = Quaternion.LookRotation(lastKnownPlayerLocation.position - this.transform.position, Vector3.up);
newRotation.x = 0.0;
newRotation.z = 0.0;
transform.rotation = Quaternion.Slerp (transform.rotation, newRotation, Time.deltaTime * 5.0);
var new2Rotation = Quaternion.LookRotation (lastKnownPlayerLocation.position - arms.transform.position, Vector3.up);
new2Rotation.y = 0.0;
new2Rotation.z = 0.0;
arms.transform.rotation = Quaternion.Slerp (arms.transform.rotation, new2Rotation, Time.deltaTime * 5.0);
}
You can calculate the rotation manually. Since you only need one angle is’t not that hard
Assuming the enemy already faces the player, you just need to calculate the arcsin.
Two problems that I see. First, you’re treating the quaternion x/y/z components as if they are Euler angles – which they aren’t. You can get the canonical euler angles of a rotation using the eulerAngles property. (And you can convert them back into quaternion notation using Quaternion.Euler.)
Secondly, you’re doing a world-transform manipulation of the arms, which complicates things. I would just modify the localRotation. (Note I assume your arms are children of the object that is doing these calculations.)
When you modify the quaternion’s components that way you’re producing non-normalized quaternions, which may cause erroneous rotations. As @chainedlupine also said, you should not mix rotations and local rotations. You should find the target direction and zero its Y component to keep it horizontal, and get the local target direction and zero its X component to keep it vertical, then Slerp rotation to the horizontal direction and Slerp localRotation to the vertical direction - like this:
function aim(){
// dirH = player direction
var dirH = lastKnownPlayerLocation.position - this.transform.position;
// dirV = arms local player direction
var dirV = arms.transform.InverseTransformDirection(dirH);
dirH.y = 0; // keep dirH strictly horizontal
dirV.x = 0; // keep dirV strictly vertical
var newRotH = Quaternion.LookRotation(dirH, Vector3.up);
var newRotV = Quaternion.LookRotation(dirV, Vector3.up);
transform.rotation = Quaternion.Slerp (transform.rotation, newRotH, Time.deltaTime * 5.0);
arms.transform.localRotation = Quaternion.Slerp (arms.transform.localRotation, newRotV, Time.deltaTime * 5.0);
}
Get rid of trying to calculate a whole new rotation for the arms and let them be dragged around the Y axis by its parent. Then when you check that it is facing the correct way rotate the arms localEularAngles.x up or down by a few degrees until the Dot Product is within a zone where you want it ? I could hash up this code for you if you like but this is just off the top of my head