# Halo-like Tank movement?

I’m working on a top-down party game with tanks and I’m finding it exremely difficult to achieve the type of player controls I’m going for. I am using a controller, no M&K.

I’m trying to have the tanks only move forwards, and rotate on their center if they have to go any other direction, until they are facing said direction and they can then proceed forwards. Kinda like the tank in Halo behaves.

Let me try to explain with an image.

I am now facing right. If I move my stick right, I want to move right. If I move my stick up, I want the tank to rotate on itself until it’s facing up, then proceed to move up.

Current blueprint looks like this:

It achieves the movement concept just fine, but the way I control the tank is completely unnatural. Moving the left stick right will always make the tank move forwards regardless of it facing right or up or any other direction, up and down will always make it rotate and so on.

I tried figuring out on my own but I am not able to, and I couldn’t find anything to help me solve this issue on the internet throughout the last couple of months.

I need help.

What you want to do is:
(1) Calculate a direction vector based on input. so right is (1, 0), up is (0,1), bottom left is (-1, -1) and so on
(2) Get the actor current forward direction
(3) Calculate the angle between the desired direction vector (step 1) and the current forward direction (step 2)
(4) If the angle is bigger than a certain small value (e.g. 5), rotate towards input direction (step 1)
(5) If the angle is not bigger (meaning our tank already faces the input direction) - add movement in the input direction

That has made things move a lot, thanks man.
I think I am starting to get the logic of it, but I still have problems.

I am struggling to figure out how to rotate towards the input direction. I looked up how to rotate towards a vector and I came by this answerthat had me experiment with the Find Look at Rotation node, but without luck. Everything I seem to do makes my tank either spin uncontrollably at lightspeed, which is admittedly hilarious albeit not my end goal, or straight-up doesn’t work.

Also, for some reason, the controls seem to be upside down. If you’d know how to help me further, I’d really appreciate it.

Regarding controls upside down - if you played some games you’ll notice some of them have ‘Invert Y’; this is pretty much a preference. You can just multiply the value by -1.

(1) Each InputAxis exec pin is executed every frame. Meaning your code will actually be executed twice each frame - only connect one of them…
(1.1) Don’t use the Axis Value pins; they are only valid during the execution of the specific node; so when ‘LS_X’ is execute, the ‘Axis Value’ of ‘LS_Y’ is invalid. There is another node to get the current axis value of an input (‘GetInputAxisValue’ iirc)
(2) If the tank is rotation too fast, you need to lower the amount of ‘Delta Rotator Z’. Add another multiply pin to the ‘Rank Rotation Speed’ and use Time.deltaTime. The effect will be that assuming the axis value is 1 (player tried to rotate as much as possible), rotation speed will be angles per second.

Just to clarify on your current value: since you’re using axis value (which I’m going to assume is 1 when rotating, but can be different depending on actual input) multiplied by rotation speed,
you’re rotating ‘Tank Rotation Speed’ degrees, for each frame.
On an 60 fps (for example), that means you’re rotating 60 * ‘Tank Rotation Speed’ degrees per second. So if ‘Tank Rotation Speed’ has a value of 45 for example, you’ll be rotating 2700 degrees per second.
In your specific example you’re actually doing it twice per frame, so that would be 5400 degrees per second.

Solved! Thanks man, you made some random guy on the internet very happy

To hopefully give back in helping someone else, here’s the blueprint that did it

btw, a few optimization you can do:

1. In the 1st branch you check if VectorLength > 0.2. UseVectorLengthSquared instead and change value accordingly.
2. Later in the 2nd branch you check the angle (acosine of dot product). Instead use just the dot product (without acos) and use a different value accordingly (e.g. if you wanted to check if angle >= 45 degrees, check if dot product >= 0.707)