- Home /
OP found the solution
Problems with joystick / controller axes being 1/-1 "way too often"
EDIT: If your controller axes "snap" to 8-directional rotations, make sure the axis sensitivity is set to a "mild" value like 1 and/or that you're using radial deadzones . Those two seem to be the main issues that make the problem rise. The reply might be useful if your joystick controls make use of the magnitude (how far from the center of the stick you move)
I'm making a 2.5d space shooter, and rather than having a "twin stick" movement I have a "thrust" button and a "turn" thumbstick: wherever you point, the ship turns that way.
I also have mouse-kb input which works well.
I have a "controller snapping" problem on my hands, where the horizontal/vertical axes only have extreme values (either -1 or 1) when the thumbstick is on the edge of its "circle".
I've tried with three pads so far: a generic Logitech, a (severely worn) 360 and a Steam Controller.
I don't know if this is what exactly is happening, but my best guess is that the axes only have the intermediate values inside a square:
Now, this is an extreme representation, but on the edge of the circle it seems very easy to be on the (1,1), (-1,1), etc. inputs compared to... anything else, really. BUT when the stick is approximately inside the square then I can rotate freely.
Just to be sure it's not a hardware/driver problem, I tried playing Beat Hazard Demo and I was able to move around as I pleased, as close to the edge as I wished.
The "Horizontal" and "Vertical" input axes that I'm using pretty much have the default parameters, and I'm using a radial deadzone, a clamping to the input magnitude and a "square to circle" transformation.
Keep in mind that this snapping problem is present with or without those things.
Is there something I don't understand about how the input axes work?
These are the hor/ver axes:
This is the relevant code, although I believe it has to do with the axis input itself, but might as well show it:
//JOYSTICK INPUT
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
//Transform square axes into circle
float horin = h * Mathf.Sqrt(1 - 0.5f * h * h);
float verin = v * Mathf.Sqrt(1 - 0.5f * v * v);
joyin = (new Vector3(horin, 0.0f, verin));
//Joystick deadzone and clamping
if (Mathf.Abs(joyin.magnitude) <= JoystickDeadzone)
joyin = Vector3.zero;
else
joyin = Vector3.ClampMagnitude(joyin, JoystickClamp);
//MOUSE INPUT
...
bool UsingJoystick = (joyin != Vector3.zero);
bool UsingMouse = ...
//Mouse input: project mouse position onto game plane
if (UsingMouse)
{
...
}
//Joystick input: depending on joystick output, turn around
if (UsingJoystick)
{
float r = 256.0f;
directioninput = r * joyin;
targetpos = transform.position + directioninput;
}
//Boost input
...
//Thrust input
...
//Actually move the ship
#region
Vector3 goalpos = transform.position + directioninput;
engine.MoveThing(goalpos, thrustinput, boostinput, true);
For reference, engine.MoveThing() simply thrusts and turns the ship towards the desired position.
Are you doing your testing with a keyboard? As in moving your character with left/right arrows?
I don't use arrow keys or anything similar for the mouse-kb input. I used the arrow keys in replacement for the joystick to test if the axes worked, but that was the end of it, now the hor/ver axes only take joysticks as input.
Sure. I was just making sure that if you were using $$anonymous$$B keys as testing, using GetAxisRaw will definitely only give input of -1/1. Unlike, GetAxis, would smooth out the input.
Answer by Eno-Khaon · Dec 24, 2018 at 07:56 PM
If your intent is to clamp to a magnitude of 1 when your combined x/y inputs exceed it, then you don't really *need* to be able to provide x/y inputs both at values of 1 on a 45° angle. A 45° angle would maximize input to sqrt(2.0) /2 or ~0.707 per axis.
However, if your intent is to have two separate axes, each capable of reaching a value of 1 simultaneously, then the logical problem instead is having a circular "joystick" to provide input in the first place.
Obviously, for any physical controllers, insisting that their analog stick should have their framing circle(s) cut into a square shape would be silly.
Realistically, a meaningful alternative at this point would be mapping a square to a circle. This would result in uneven shifts in input values with certain kinds of movement, but there's also no real means of avoiding that when deforming the inputs in the first place.
Thanks for the answer, but I already mapped the square to the circle. Turns out I copied down the formula wrong so there's that, but the problem still persists. I figured I'd do a GIF to show exactly what's happening: The blue stick represents the GetAxis("hor"/"ver")s, while the pink one the "circled" axes.
There should be a white one for the raw axes but it coincides with the blue one.
In the GIF I am moving the stick around the edge at constant speed, and clearly the axes are not playing along.
This happens regardless of radial deadzone and clamping (I set them respectively to 0 and 4)
$$anonymous$$erry Christmas by the way
Hmm... on one hand, maybe I misunderstood exactly what you were going for. If your inputs are rounded (analog stick) and you need them to become squared, then you would potentially need a circle-to-square conversion (secondary link) ins$$anonymous$$d.
On the other hand, looking back over your original script sample, there may be a few issues there regardless.
For example, you wrote the x and y-axis scaling incorrectly. The square-rooted values need to be swapped.
float horin = h * $$anonymous$$athf.Sqrt(1 - 0.5f * h * h);
float verin = v * $$anonymous$$athf.Sqrt(1 - 0.5f * v * v);
... should be...
float horin = h * $$anonymous$$athf.Sqrt(1 - 0.5f * v * v);
float verin = v * $$anonymous$$athf.Sqrt(1 - 0.5f * h * h);
How does the behavior compare before mapping the inputs to a circle? In theory, a perfectly calibrated analog stick would logically only reach ~0.707 on each axis when held diagonally, so how clean of a circle does the hardware make in the first place?
Additionally, just for reference, does the ship rotate smoothly with a deadzone of 0 (and based on GetRawAxis(), logically), or does it still snap briefly? I've dealt with shoddy analog sticks before, so I hope to be able to rule out faulty hardware as well.
As I said in the reply, I've already spotted the error in the formula. In the OP I also said I tried with three different controllers, from good-as-new to shoddy, and still have the snapping issue. I tried them on a polished game and I'm able to use the sticks as I wish. Also come to think of it, square or circle input shouldn't matter, because in my case I don't care about the magnitude but only the angle , and that doesn't change with the transformation. I'm confident that Beat Hazard uses an input axis system as well and it doesn't seem to have the same snapping issue with the same controllers.