Page 1 of 1
How to prevent drifting from analog movement?
Posted: Sun May 26, 2024 6:38 am
by DOMINOSRULZ
Hello,
I have been trying to get input movement from a controller working in a project I am working on, but I am stuck on the movement regarding the analog stick. I have added something like this for the movement:
Code: Select all
local xaxis = joystick:getAxis(1)
downPaddle.x = downPaddle.x + (xaxis * downPaddle.moveSpeed)
It does move the player correctly, but when the stick is not moved in any direction, the player starts drifting instead of stopping at once. From what I understand, there needs to be a way for the game to know that the analog stick has stopped being used. However, I cannot find any way to do this. I've tried thinking of some solutions myself, but to no avail.
Are there any examples as to how this can be fixed?
Re: How to prevent drifting from analog movement?
Posted: Sun May 26, 2024 9:50 am
by MrFariator
All analogue sticks tend to report some infinitely small, miniscule movements near the default resting point, particularly if the gamepad has seen some regular use over the years. Like, yes, physically it might appear like the stick should be resting at 0, but either the stick has worn down (and as such can't rest in the center perfectly anymore), or the sensors are more sensitive than you are expecting.
So, usually the go-to answer is to set a certain "deadzone" for the analog stick readings. Meaning, the value needs to surpass a certain value, before the game starts registering it, and actually start acting on it. For example, on an Xbox Series X gamepad, I think the value reported by getAxis() should perhaps be around 0.1 or higher, before it's detected as movement. You may adjust the minimum value up or down according to your liking, or which brand of gamepads you're working with. Some games provide the option to set the deadzone size, but this is not strictly necessary so long you find a range that works for the most common brands.
In your case specifically, because the paddle movement speed seems to be tied to how much you tilt the joystick, you might want to also convert the read value from [minimum,1] to [0,1] (basically normalize it), if you want to make it a smoother gradient.
Re: How to prevent drifting from analog movement?
Posted: Sun May 26, 2024 12:38 pm
by pgimeno
Here's a function to do what MrFariator said. Generally, I'm all for teaching how to fish instead of giving fish, but I made an exception in this case because it's not easy for everyone to work out the linear transform that makes the dead zone work.
In addition, the most common formulation may suffer from a precision problem where it might not return exactly 1 or -1 when the joystick function does, and I've written this function with that in mind. It will return exactly 0 when within the dead zone, and exactly 1 or -1 when joystick:getAxis does. It also returns -0 when within the negative part of the dead zone, allowing you to check the zero crossing during testing.
Code: Select all
local DeadZone = 0.1
local function getAxis(joystick, axis)
local value = joystick:getAxis(axis)
local sign = value < 0 and -1 or 1
local DynamicRange = 1 - DeadZone
value = math.min(1 - math.abs(value), DynamicRange)
return sign * (1 - value / DynamicRange)
end
Just replace joystick:getAxis(n) with getAxis(joystick, n) to make the deadzone work, and adjust the deadzone to your liking.
Re: How to prevent drifting from analog movement?
Posted: Sun May 26, 2024 2:49 pm
by DOMINOSRULZ
MrFariator wrote: ↑Sun May 26, 2024 9:50 am
All analogue sticks tend to report some infinitely small, miniscule movements near the default resting point, particularly if the gamepad has seen some regular use over the years. Like, yes, physically it might appear like the stick should be resting at 0, but either the stick has worn down (and as such can't rest in the center perfectly anymore), or the sensors are more sensitive than you are expecting.
So, usually the go-to answer is to set a certain "deadzone" for the analog stick readings. Meaning, the value needs to surpass a certain value, before the game starts registering it, and actually start acting on it. For example, on an Xbox Series X gamepad, I think the value reported by getAxis() should perhaps be around 0.1 or higher, before it's detected as movement. You may adjust the minimum value up or down according to your liking, or which brand of gamepads you're working with. Some games provide the option to set the deadzone size, but this is not strictly necessary so long you find a range that works for the most common brands.
In your case specifically, because the paddle movement speed seems to be tied to how much you tilt the joystick, you might want to also convert the read value from [minimum,1] to [0,1] (basically normalize it), if you want to make it a smoother gradient.
pgimeno wrote: ↑Sun May 26, 2024 12:38 pm
Here's a function to do what MrFariator said. Generally, I'm all for teaching how to fish instead of giving fish, but I made an exception in this case because it's not easy for everyone to work out the linear transform that makes the dead zone work.
In addition, the most common formulation may suffer from a precision problem where it might not return exactly 1 or -1 when the joystick function does, and I've written this function with that in mind. It will return exactly 0 when within the dead zone, and exactly 1 or -1 when joystick:getAxis does. It also returns -0 when within the negative part of the dead zone, allowing you to check the zero crossing during testing.
Code: Select all
local DeadZone = 0.1
local function getAxis(joystick, axis)
local value = joystick:getAxis(axis)
local sign = value < 0 and -1 or 1
local DynamicRange = 1 - DeadZone
value = math.min(1 - math.abs(value), DynamicRange)
return sign * (1 - value / DynamicRange)
end
Just replace joystick:getAxis(n) with getAxis(joystick, n) to make the deadzone work, and adjust the deadzone to your liking.
Thank you both very much. The solution you both proposed worked, and the paddle moves just as it is supposed to. I have also taken notes on what was said, and will very much keep this in mind when working on my next project if it ever needs controller support.