# Can't get rotation relative to parent to work properly

I’m tinkering with a little twin stick tank game to improve my skillset (and to be busy) but I can’t figure something out.

The tank is a rigidbody with 4 raycasts as a suspension, or wheels. I rotate the tank using my gamepads’ left stick Vector2 and accelerate using the magnitude of that input.

``````Vector2 movement = gameplayActionmap.FindAction("Movement").ReadValue<Vector2>();
``````

So far so good. Works like a treat. Movement and rotation also work in relation to the angle of the camera, so moving the left stick to the right will always result in the tank moving to the right. If I point the stick left the tank will always move to the left. The same for up and down an pretty much any other direction.

The turret is a whole other story. The turret GameObject is a child of the tank, but I cannot for the life of me figure out how to make the turret stick to local rotation but still point in the direction of where I’m point the right stick on the gamepad. Right now this is the code, which is also pretty much how I handle rotation on the tank itself:

``````        Vector2 turretRotate = gameplayActionmap.FindAction("Turret").ReadValue<Vector2>();

float turretX = turretRotate.x;
float turretY = turretRotate.y;

Vector3 hTurDir = Camera.main.transform.right * turretX;
Vector3 vTurDir = Camera.main.transform.forward * turretY;
Vector3 turDir = hTurDir + vTurDir;

var turRotation = Quaternion.LookRotation(turDir);
if (turretX != 0.0f || turretY != 0.0f)
{
turret.rotation = Quaternion.Slerp(turret.rotation, turRotation, Time.deltaTime * turretRotateSpeed);
}
``````

I figured I need Quaternions because I’m dealing with the angle of the right stick on the gamepad, but that’s where my lack of knowledge kinda shows. I tried localRotation = but that messes with the aiming (i.e. the turret won’t aim in the direction of where I’m pointing). With the above code the turret points in the right-ish direction, but aligned with the Camera.main.transform, because I want it to work relative to the angle of the camera. What I don’t want is the turret to rotate in every axis independent of its parent.

Don’t know if this all makes sense, but how do I make it so that the turret only rotates on the Y-axis, relative to it’s parent, but still points in the direction of where I’m point the right stick on the gamepad?

The answer to your specific question will have a lot to do with how you parent and set stuff up.

But at the bottom of it all, if you have to coaxial rotators (the body of the tank and the turret of the tank), each one can be simply set to the Atan2() of the X/Y inputs.

That’s how I did it for my basic twin-stick tank demo. Check this script:

Most of it is input gathering, as that is part of a touch input package (proximity buttons), but the interesting parts are the `UpdateMoving()` and `UpdateShooting()` methods.

The above also supports backing your tank up (optional boolean), and also making the turret slew with the tank body as it turns (also optional).

Combined with choosing interesting rates of rotation you can get some fairly interesting and challenging little twinsticker tank situations going.

1 Like

I took a look at your script, which contains some very nice features, and borrowed the way you handled rotation for the turret, but the problem didn’t go away. It seemed that no matter what I did, whenever I used Quaternions or Eulers to only affect the Y axis, the X and Z axis would also change and not stay 0 like I wanted them to. I also saw an instance where the turrets’ X-axis would take the Z-axis of it’s parent (the tank body) and the Z-axis would take the X-axis of the parent. So it was quite frustrating that this just wouldn’t work, not matter what code I threw at it.

So I deleted everything related to the turret rotation and started over. Converted both thumbsticks of the controller into 360 degree floats (using Atan2, as you mentioned) and tried to tie the float/angle of the right thumbstick to the Y-rotation of the turret. I used localEulerAngles which kept the turret in place on the X and Z rotation and then used the angle of the tank as an offset so that I wasn’t aiming relative to the tanks’ movement.

``````turret.localEulerAngles = new Vector3(0, angleAim - angleTank, 0)
``````

That’s it. That’s all I needed to rotate the turret in the direction of the right thumbstick, independent of how the tank is rotated, but parented to the tank. So in the end I didn’t use anything from your script, but I still want to thank you for taking the time to respond Also gonna favorite that tank demo of yours for inspiration later on.

1 Like