jibbsmart
@jibbsmart

The analog stick is a 2D input, but driving games tend to treat it as a 1D input. This is understandable. A steering wheel is a 1D input as well. But a steering wheel has some advantages over a thumbstick:

  • Far greater range of motion -- This allows drivers to be very exacting with how tight their turn is;
  • No deadzone -- In games (and especially controllers/gamepad), a "deadzone" is a range in which an analog input is ignored. Because an analog stick won't return exactly to its centre when the player releases it, games will normally have a deadzone within which the stick is assumed to be at its centre.

Driving games (or games where you drive at times) will usually ignore the vertical axis of the thumbstick input and only use the horizontal axis. But with just a few lines of code, every driving game can offer far more steering precision to players, with no extra settings, and no inconvenience to players who prefer to stick to one axis.

2D steering really is one weird trick for better steering in your game.

Here's how it works:

We use the angle of the stick to decide how hard we're turning. 90 degrees to the left is still a hard left. 90 degrees to the right is still a hard right. 45 degrees in either direction is a half-strength turn in that direction. Straight forward is no left or right turn. But here's the magic:

The slightest left or right rotation of the stick will give you the slightest turn in that direction.

Because the player has tilted the stick forward, they've left the 2D deadzone in the middle and indicated that they want to engage the steering wheel. So the game can honour even the smallest turn of the stick.

See Aaron McDevitt explain the benefits of that in his phenomenally tight racing game Aero GPX on Twitter:

And on YouTube:

But let's go back to the GIF from earlier and look at the Trackmania example. The game doesn't actually support 2D steering. I'm using an input remapper I'm involved with (and created originally) called JoyShockMapper to force 2D steering into the game. Here I'm using LEFT_ANGLE_TO_X to convert the stick's 2D position into a 1D position (accounting for deadzones) and let me put 2D steering into any game. I showed it in Trackmania because the big, visible wheels and the importance of precision just make it a great game for demonstrating it.

But forcing it into games doesn't always work. It's difficult/clunky to make this work on console (using remote play through a computer). And it can't account for the game state -- Aero GPX disables 2D steering when you're airborne so that you can still control the pitch of your vehicle. Rocket League would benefit from 2D steering, too, but needs that game state awareness to still allow flips and air control.

This is why we need games to support this natively. The only games that currently do as far as I know are Fortnite and Aero GPX. The former is free, and the latter has a free demo, so you can try it out yourself! And JoyShockMapper is free open source software, so you can set it up in most PC games if you're keen. But game devs, I want to see it native in your games.

When done right, 2D steering still lets you only slightly engage your stick for a gentler turn. It's very simple to combine the angle and the magnitude of the stick position. This means that players who continue to steer using only the horizontal axis get identical behaviour to before you added 2D steering. They don't need to play any differently if they don't want to, and there is no need to add a new setting to control this!

Like with 1D steering, the player won't use the stick exactly in the horizontal axis, though, even when they want to. So I recommend having a small angular outer deadzone so players can confidently do their hardest turns without having to be incredibly precise about the stick angle.

Here, have a code example from my blog post 7 Building Blocks for Better Controls:

// +- angular range from horizontal that'll be treated as a horizontal input
float OuterDeadzone = 10.0;
 
// this will return a value between -1 and 1, inclusive, for how hard the vehicle is turning.
// assume circular deadzone is already applied
float StickToSteeringStrength(Vec2 stick) {
   if (stick.X == 0.0 && stick.y == 0.0) {
      return 0.0;
   }
 
   float absY = abs(stick.Y);
   // using absolute Y means the back half of the stick mirrors the front
   float stickAngle = atan2(stick.X, absY);
   // convert to degrees because our outer deadzone is in degrees
   float absAngle = abs(stickAngle * 180.0f / PI);
   // remap to [-1, 1] range without the deadzone
   float angularStickStrength = sign(stickAngle) *
      clamp(absAngle / (90.f - OuterDeadzone), 0.f, 1.f);
   // some games apply a power curve on their traditional steering.
   // here, you would apply that to the magnitude
   float magnitudeStickStrength = stick.Magnitude();
 
   return angularStickStrength * magnitudeStickStrength;
}

2D steering isn't exclusively about removing the deadzone in the middle when players don't want it. It's also about the range of movement. By linearly mapping the angle to steering strength, players can more easily make consistent adjustments to how hard they're turning. Having almost half the circumference of the stick's circle instead of diameter - inner deadzone - outer deadzone means players have noticeably more precision over their turning circle.

The only real challenge is teaching players to use it.

An invisible, unintrusive feature is no use if no one tries it. You're going to have to tell players about it. And as more developers tell their players about it, more players will come to want it or expect it when driving in any kind of game. Wouldn't it be great to get ahead of them on that and offer distinctively good driving controls in your game?


pizzaforfree
@pizzaforfree

Congrats~ You just got someone that hates having to use remapping software to willingly download a remapper! Steering precision is the reason I play Trackmania on controller instead of keyboard. If you can give me near-wheel precision with a controller, I'll download it in a heartbeat! In fact, I already did! Now I can be even worse at Trackmania than I already am (until I properly learn this new control scheme)!

Now, for other players that want to make use of 2D-steering but don't need any of the other features JoyShockMapper offers, here's some brief instructions to get you going:

  1. Connect your controller and open JoyShockMapper dot exe.
  2. A command line like window will have opened, that's our remapper. Type "VIRTUAL_CONTROLLER = controller type" where controller type is either XBOX or DS4, depending on which controller you want to emulate. So, if you want it to emulate an xbox controller, it should look like VIRTUAL_CONTROLLER = XBOX. Hit enter.
  3. Type LEFT_STICK_MODE = LEFT_ANGLE_TO_X. Hit enter.

And with that, you're ready to play! Ideally, you'd set up an AutoLoad file for the games you're using this with. I don't know how to do that, yet, unfortunately, so I can't offer that help. Hopefully this is still useful to folks, though!


You must log in to comment.

in reply to @jibbsmart's post:

argh.. with the addition of this other dimension, i'll potentially become just as terrible at steering as i am at other activities using precision in both movement dimensions of a gamepad stick.. i just can't keep track of them both at the same time without looking!

in reply to @pizzaforfree's post:

Thanks so much for adding that info! I'm glad you were able to get going so quickly.

Those who get an error with VIRTUAL_CONTROLLER = XBOX will need to install ViGEmBus, which lets applications like JoyShockMapper create and connect virtual controllers.

Also, to let JoyShockMapper skip the game's built-in deadzone when you tilt the stick forward, add: LEFT_STICK_UNDEADZONE_INNER = 0.1

At least, that's what's in my Trackmania config. If the number is too high, you'll be able to tell because the stick will be slightly tilted even when you're not touching it. This is intentional and it helps with quickly iterating and finding the exact value of the built-in deadzone for JSM to try and skip.

Also, put all that stuff in a file called Trackmania.txt and put it in the Autoload folder, and then JSM will automatically load that config when Trackmania is in focus (as long as JSM is running).

My config looks like this:

GyroConfigs/xbox.txt # comes with JSM, sets up the Xbox controller
LEFT_STICK_MODE = LEFT_ANGLE_TO_X
LEFT_STICK_UNDEADZONE_INNER = 0.1

Oooh, thanks for the info! I might have to do some experimenting with that.

And no problem! I found the instructions a bit on the difficult side to understand, personally (might just be tired though), so I just figured I'd put this out there for others that might struggle with it.