How To Rotate My Tank Turret Around Local Z Axis?

I’ve got a tank playable character I’m working on and I’m trying to get the roll and pitch axis of the turret to match that of the tank chassis, so that when the chassis changes angles (like sitting on uneven terrain) then the turret should match the rotation of the chassis.

I’m controlling the rotation of the turret with my mouse with this blueprint:

Currently, when the chassis changes angles, the turret does not follow:

I need The turret to be able to match the angle of the chassis no matter what kind of terrain it is sitting on, but still be able to rotate with the mouse independently of the chassis.

Could someone please point me in the right direction for how to achieve this? Thank you.

You need to make sure the components that make the turret and in a group, and that group is connected to the body. That will handle a lot of it.

Then use ‘add local rotation’ node in Z to move the turret as per your BP.

1 Like

So I’ve been at this a few days now and unfortunately I’m no closer to getting this figured out. By group, you mean a parent child component relationship right? something like this?
Group

Also tried the add actor local rotation node but when I used that it caused my turret to spin uncontrollably. I may have done something wrong there in terms of blueprint configuration, not sure. Still very new to unreal engine.

Best results I’ve gotten so far were to set my turret pitch and roll to the root component pitch and roll. That has taken care of some of it, but when my tank goes airborne or travels over very uneven terrain the turret still detaches from the chassis and/or bounces around.

Here’s a video, incase my first picture didn’t really illustrate what’s going on. If you or anyone else could offer me some further advice on how to attack this, that would very much help, Thanks.

It looks like you have the correct component hierarchy, which is the most important thing.

The only thing you should be doing is changing the relative rotation on the turret with respect to the body ( because that’s how they move ), in Z.

If you stick with that, you won’t get this tilting I see.

The problem remains ( as I’m sure you know ), that using ‘set relative rotation’, will glitch when it gets to 180. There are two ways around this

  1. ONLY use these nodes :slight_smile:

‘set relative rotation’
‘combine rotators’ ( NOTE, it does matter which order you put the rotators in )
‘delta rotator’

You basically use the two rotator nodes to calculate what position you’re going to set the turret to next, and then use the ‘set relative rotation’ node to do that. This will be with a timeline. The reason we use those nodes is, because internally, they use quaternions which avoid the 180 snapping problem.

  1. Use ‘add relative rotation’. DON’T use a timeline with this node. If you think about it, you’re adding rotation every frame, it’s no wonder it spins. If you want to use this node, you need to do it with finterp.

Here, the player would choose ‘rotate right’ ( for instance ), and you decide you’re going to add 30 degrees to the turret rotation, and use ‘add local rotation’ with an finterp on tick. It’s a very different method from above. It depends on how you want to setup the movement.

With this option, if you bothered to print out the Z rotation, it would be doing crazy things at 180, but we don’t care, because we’re only dealing with relative changes.

Does this make some sense?

1 Like

Thanks for your time and advice.

I think I’m understanding you. I rigged up this set of nodes based on what I think you wrote for your second method and its working pretty well.

I had to make a change to my Turret static mesh to get it working properly though. I had to change its rotation transform property from ‘world’ to ‘relative’ then with the revised BP, the turret rotates and holds angle according to the tank body. No more tilting! Fantastic! However, had I kept the transform property on ‘world’ it would continue to tilt when the tank body changes angles.

BUT, I had originally changed that rotation property so that the turret would hold its direction regardless of the rotation of the body. Now, when the body turns so does the turret. I know this is outside the scope of the original question, so if I should make a new post instead just let me know.

Otherwise, any suggestions to get the best of both worlds? I’d imagine I’d want to do something like checking for mouse input and if there isn’t any, to set the turret rotation to camera forward vector or something like that. Any thoughts?

Turret Transform set to ‘World’

Turret Transform set to ‘Relative’

1 Like

I’m amazed it’s working at all, actually :slight_smile:

You have to either add local or add relative, you can’t do both :wink:

So that you know how to do finterp on tick, and to encompass your ‘idle angle’ requirement, you need this sort of thing

You see, the tick is always trying to pull the turret back to zero, but it’s also possible to turn it with the mouse.

Tell me how it goes…

Thanks for your help.

Unfortunately that on tick node set doesn’t do what I need it to do. When I use it, all it does is pull the turret to the front of the tank body, instead I need my turret to be able to hold whatever its current yaw angle is regardless of the rotation of the tank body.

I’ll try some different variations of your node setup and see if I can come up with anything that might work better. Will keep updating as I go.

That was as intended, sorry, misread that part of your request.

When the player changes the yaw, put that in a variable, and make that the target of the finterp node. Everything else, the same.

Sorry, I’m a bit confused about how that works in this context. If I set the relative rotation as a variable and set that as the FInterp target, then relative rotation will always be set to that number, relative to the rotation of the tank body. That’s not what I’m after though.

Essentially what I’m trying to do is point the turret towards its world yaw position regardless of what the world rotation of the tank body is. So say the world rotation of the Turret is 130, but the current relative rotation is 30. That relative rotation is going to have to keep changing in order to continually stay pointed at that 130 world rotation.

So for whatever world yaw point the turret is currently pointed towards, I want it to maintain that direction unless moved by mouse input. So I’d imagine I need to make something where as the rotation of the tank body changes, the turret counter rotates by the same amount so that regardless of tank body rotation, the turret maintains the world yaw direction it’s pointed towards . I would assume I’d need some sort of number factor or formula to get that figured, but so far I’m coming up short.

I thought I could figure out a formula to get the turret world rotation out of the relative rotation by doing some math, and I found that under certain circumstances the turret world yaw is equal to the turret relative yaw + tank body world yaw, but since yaw only goes to 179.9 in either direction, that formula goes out the window as soon as the combination of the turret relative yaw and body world yaw are greater than 179.9.

Closest I’ve been able to get it to so far is to set the FInterp target to the inverse transform rotation yaw of the world rotation of the tank body. That gives me the performance I’m looking for but overwrites mouse input so I cant point the turret anywhere but towards the inverse transform rotation yaw.

Here’s what that BP looks like:

And here’s what that looks like in engine:

Am I way overthinking this? I cant seem to figure out an easy way of making this happen according to the performance I’m looking for.

Sorry, we’re at cross purposes…

Ok. Then you have to go for ‘look at rotation’, using only the Z. The problem is, what to look at.

The only thing you have to watch for, is that MaxDistance is encompasses the tank’s possible play region. IE, it’s the radius of a circle outside which, the tank will not venture.

1 Like

I cant seem to make this work for me. The suggested bp doesnt seem to respond to mouse input, and since the tick function uses set world rotation, again i run into the issue of the turret detaching/tilting from body in air or uneven terrain.

I’m sorry for being such a bother, I’m starting to feel like I’m sending you on a wild goose chase.

Let me try to rephrase what I’m looking for. I don’t think I’ve done the greatest good job of being clear so far.

I am after two separate things.

  1. Keeping turret attached to tank body, regardless of whether tank body position is in air, uneven terrain, etc…

  2. Separating turret rotation from tank body rotation. I would like to point the turret at a location in world space, and have the turret maintain that direction regardless of the rotation of its parent body, until given new rotation via mouse input

I can achieve one of these two qualities but not the other by changing the rotation transform settings of my Turret Mesh.

If I set the mesh rotation to ‘Relative’, I get #1 but not #2:
TurretMeshTransform

and if I set the mesh rotation transform to ‘World’ or ‘Absolute Rotation’, then I get #2 but not #1:
TurretMeshAbsoluteRotation

Seems like I’m getting nowhere with getting the turret rotation performance I’m after. But if I set my turret mesh transform to ‘Absolute Rotation’ then I get the exact rotation performance I want, but the turret mesh doesn’t stay attached to the body in air or over bumps/hills.

Maybe there is an easier way to attack this problem? Perhaps I should attack it from the other side and keep the mesh rotation set to ‘Absolute’ and just work on keeping the turret attached to the body instead? I appreciate your time and help you’ve given me so far.

Thoughts?

OMG! :smiley:

Sorry, didn’t test it on ‘rugged’ terrain. The mouse input not working, that’s something else…

I will get back later, I think it’s going to be a bit of a fiddle.

UPDATE: Yes, still use ‘look at rotation’, but then only use the Z portion of it, and you have to put it through ‘inverse transform rotation’ to get it as local rotation for the turret.

That’s the gist of it, I will try and come back later with the code.

The second piece of code should read

This DEFINITELY works :slight_smile:

2 Likes

YES this DOES DEFINITELY work! Thank you SO MUCH!!!

I have one final request as I’m not just looking to create this project, I’m also trying to learn as much as possible along the way.

Any chance I could ask you to explain to me some of the detail of how and why this code works the way it does?

Sure thing.

We want the turret to point at a location in the world, no matter what. The best way to do that is ‘look at rotation’. The problem with that node, is that it’s ‘world’, not relative.

You could try and figure out the conversion between relative and world rotations yourself, but after leaving the asylum, you’d realize it’s not such a great idea.

Much better to use that ‘inverse transform rotation’. It takes the world transform of the actor and the world rotation, and converts it into a relative rotation. Then all we need to do is get rid of the X and Y terms, because we only want to move the turret in Z.

There a whole bunch of these nodes for location, rotation, scale etc. And a bunch going the other way, relative to world, just leave the ‘inverse’ off the node name.

:slight_smile:

1 Like

Thank you so much for all you’ve done for me. I very much appreciate it!

1 Like

I am doing the same thing and I tried following this but I guess I’m doing it wrong. If you guys are still around…