I have been pulling my hair out trying to fix this one. So I have an AI controlled vehicle that has a turret on top. The turret is its own game object and has a script that turns to face and shoots at the enemy. This all works great except for one thing, when the player gets to a certain distance away from the turret, it flips 270 degrees along the Z axis.
It still tracks accurately along the Y axis, but looks ridiculous. I even have code binding it to zero along the X and Z axis and still no dice. Here is the code:
Quaternion rotation = Quaternion.LookRotation(Target.position - transform.position, Vector3.forward);
rotation = Quaternion.Euler (0f, rotation.eulerAngles.y, 0f);
transform.rotation =
Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Damping);
All the starting rotations are zero and it isn’t a parenting issue as far as I can tell. The most confusing part is that it is a distance related issue, I didn’t even think that could matter when dealing with Quaternions.
As an alternative solution you can try is this:
- Make the turret’s transform look at an empty guide game object with the Transform.LookAt() (and not the Quaternion.LookRotation()) method.
- Make that guide game object smoothly follow the enemy with any kind of smoothing curve of your liking.
This way you can vary the smooth-follow curve either by changing its parameters or even changing the analytical form of the curve itself. In fact this could even be according to your turret pilot’s snappiness/reactiveness in case it’s ai-controlled.
Also I believe this solution prevents you from dealing with any quaternions at all. But you have to provide world’s up vector so it’s more of a terrain-base battle oriented solution. If you’re free barrel-rolling in space, that might not work.
GameObject enemyGameObject = ...;
GameObject guideGameObject = ...;
GameObject turretGameObject = ...;
guideGameObject.transform.position = Vector3.Lerp(guideGameObject.transform.position, enemyGameObject.transform.position, 0.3F);
turrentGameObject.transform.LookAt(guideGameObject);
I believe the problem might be because of the second parameter on the LookRotation, since you registered transform.forward as an up axis, try not writing any second parameter or writing Vector3.up instead.
I solved in way simpler a way than I could have guessed. I am not sure why this was a problem but it seems that the default rotation was -90 degrees along the Z axis? All I had to do was change a single value from 0f to 90f and it works exactly like I want it to. Here is the completed code:
Quaternion rotation = Quaternion.LookRotation(Target.position - transform.position);
rotation = Quaternion.Euler (0f, rotation.eulerAngles.y, 90f);
transform.rotation =
Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * Damping);
I also removed the vector3.forward as lineupthesky suggested. It didn’t do anything which I guess shows how unnecessary it was. If anyone thinks they know why this happens I would love to hear it. The script was attached to a zeroed game object although it acts like it isn’t.