Get rotation of a randomly rotating turret on a moving tank (to Spawn missiles in that direction)
I've fried my brain with this one and would very much appreciate any help anyone can give! Looked at similar questions and answers but can't get my head around these rotations...
I have a tank with a random rotation on its turret (it sweeps left and right, changing direction randomly).
I have a missile spawner as a child of the turret with a script which aims and fires along the axis of the turret:
In F3DMissileLauncherSimplified.cs, attached to the MissileLauncher child, I'm using the following code in the Fire() method (this is randomly triggered so that the missiles launch at varying intervals):
Transform barrel = transform.parent;
float turretRotation = barrel.parent.parent.parent.localRotation.eulerAngles.z;
Quaternion dirAngle = Quaternion.Euler(0, turretRotation, 0);
Transform tMissile = F3DPool.instance.Spawn(missilePrefab, barrel.position, dirAngle, null);
The Spawn method seems pretty standard and is defined as follows:
public Transform Spawn(Transform obj, Vector3 pos, Quaternion rot, Transform parent)
The situation is slightly complicated by the fact that this is a Blender mesh imported with a 270 rotation on the x axis but all other transforms are aligned as you'd expect. (See screenshots above)
This all works fine when the tank is stationary but once I added a NavMeshAgent and a random roaming script, making the tank move around (in addition to the turret rotation) the missiles no longer come out in line with the turret, but off at varying angles.
I feel stupid. Surely getting the rotation angle, looking down a turret, can't be this difficult!
Answer by baroquedub · Apr 29, 2016 at 08:59 PM
Can't seem to add a reply to @Scribe (too many replies on the same post?) but this is definitely his answer. Works great. Thank you! I'd obviously been over-thinking this, being still relatively new to Unity.
So based on his reply, the solution is:
Transform barrel = transform.parent;
Quaternion dirAngle = Quaternion.LookRotation(-transform.up, transform.forward);
Transform tMissile = F3DPool.instance.Spawn(missilePrefab, barrel.position, dirAngle, null);
For anyone interested, checking LookRotation in the docs, explains the solution. This is how to get the angle in the direction I want:
Quaternion LookRotation(Vector3 forward, Vector3 upwards);
and because the gameobject to which the script is attached (the MissileLauncher) has an odd rotation the LookRotation is adjusted accordingly:
'Forward' is actually the reverse of the object's y axis (-transform.up) which is green 'Up' is my object's forward axis (positive z) the arrow in blue.
Comparing the object's axis with the world axis explains why things have to be adjusted. To get the 'forward' parameter of the LookRotation function you have to go along the object' Y axis (in reverse) To get the 'up' parameter you have to go along my object's z axis.
Thank you for pointing that out. I hope this helps other newbies flummoxed by all these rotations and axis!
Nice description, much better explanation than my own :) glad you got it working!
Answer by AlbinoStoic · Apr 29, 2016 at 01:34 AM
This is easy if your firing script is under the barrel and not the tank!
// C# - Called by Update() on the Barrel
void Fire(){
// Find out what the barrel thinks forward is.
Vector3 direction = transform.TransformDirection(Vector3.forward * 1f);
// Spawn the bullet at our position + direction + rotation
GameObject bullet = Instantiate(bulletPrefab, transform.position + direction, transform.rotation);
// Send the bullet speeding off "forward" (this only works because we rotated the object when we created it.)
bullet.GetComponent<Rigidbody>().velocity = new Vector3(1f, 0, 0);
// Do your Spawn or Network.Spawn now that it's ready.
}
Sorry. I've seen similar things posted around but it's not what I'm asking.
$$anonymous$$y spawn pool script needs the direction angle.
Also, I've got my Firing script on the $$anonymous$$issile Launcher (the last child in the hierarchy) not the parent tank. (Have a look at the screenshots and you'll see what I mean).
Using your logic, I've tried:
Transform barrel = transform.parent.parent.parent.parent;
Vector3 direction = barrel.TransformDirection(Vector3.forward * 1f);
Quaternion dirAngle = Quaternion.Euler(direction);
Transform t$$anonymous$$issile = F3DPool.instance.Spawn(missilePrefab, transform.parent.position, dirAngle, null);
but that does the same thing, firing at odd angles
If you have the direction as a vector3, then you can use Quaternion.LookRotation to get the rotation to apply, try:
Quaternion.LookRotation(direction, Vector3.up);
The problem is I don't know how to get the direction from this randomly rotating turret on a randomly moving tank. There isn't a target as such, it just fires randomly in all directions.
The thing I don't understand is why method I use to get the rotation of the turret (when the tank is stationary) stops working when the tank is made to move by the Nav$$anonymous$$eshAgent.
Thanks for your help though :) I've altered the title of my question to better explain what I'm trying to achieve. I can see now that I wasn't being very clear.