I’ve been recently trying to make a 2D bullet-hell shooting game using GUI’s on Roblox but I’ve been getting this issue where the player moves very badly. I need the player to move and also when you hold the arrow keys, instead of moving once, it keeps moving until you release it. I also know how to use UserInputService but it just handles the keyboard input once, not when holding. Any help? Thanks for reading.
Can’t speak to the player moving badly because you aren’t showing the code that handles that so it wouldn’t be possible. For the holding the keys down take a look at this post:
sorry, my bad. here is the code that i’ve been using for all of this:
local UIS = game:GetService("UserInputService")
local Keys = {
Up = Enum.KeyCode.Up;
Left = Enum.KeyCode.Left;
Right = Enum.KeyCode.Right;
Down = Enum.KeyCode.Down
}
local ButtonToMove = script.Parent
UIS.InputBegan:Connect(function(input)
local LocaleKeycode = input.KeyCode
if LocaleKeycode == Keys.Up then
ButtonToMove.Position += UDim2.fromScale(0,-0.05)
elseif LocaleKeycode == Keys.Left then
ButtonToMove.Position += UDim2.fromScale(-0.05,0)
elseif LocaleKeycode == Keys.Right then
ButtonToMove.Position += UDim2.fromScale(0.05,0)
elseif LocaleKeycode == Keys.Down then
ButtonToMove.Position += UDim2.fromScale(0,0.05)
end
end)
and sorry but the post you sent regarding my issue didn’t work well for my game since i was missing a couple variables. if you have tested the code above, the player moves very stiff, and i want it to be smooth and steady to control
I would avoid using .fromScale
as it means players on different resolutions move at different speeds. Using .fromOffset
means you’re using pixels, rather than a percentage of the display size.
Well, the size of the game screen is also different from device to device, so using fromScale is correct in this case.
When that is said, Hi!
You’re almost there with the movement. You could possibly do this:
local MovementInterval = 0.01
local MovementDistance = 0.05
local KeysDown = {}
UIS.InputBegan:Connect(function(input, gameprocessed)
if gameprocessed then return end
local LocaleKeycode = input.KeyCode
if LocaleKeycode == Keys.Up then
if KeysDown[LocaleKeycode] then return end -- Just makes sure that we cannot send two InputBegan of the same type, before we at least have had a InputEnded of the same type, just a debounce to be fair.
KeysDown[LocaleKeycode] = true
repeat
ButtonToMove.Position += UDim2.fromScale(0,-MovementDistance)
task.wait(MovementInterval)
until not KeysDown[LocaleKeycode]
elseif LocaleKeycode == Keys.Left then
--Repeat yourself for the rest of the keys
end
end)
UIS.InputEnded:Connect(function(input, gameprocessed)
if gameprocessed then return end
local LocaleKeycode = input.KeyCode
if LocaleKeycode == Keys.Up then
KeysDown[LocaleKeycode] = nil
elseif LocaleKeycode == Keys.Left then
--Repeat yourself for the rest of the keys
end
end)
Edit: Just be aware, that with this method the movement-directions is not in sync, meaning that the movement in two directions wont be done at the exact same moment, since it’s multiple repeat loops.
Just updated your code a bit to take care of multiple movement:
local MovementInterval = 0.01
local MovementDistance = 0.005
local KeysDown = {}
local downCount = 0
UIS.InputBegan:Connect(function(input, gameprocessed)
if gameprocessed then return end
local LocaleKeycode = input.KeyCode
if LocaleKeycode == Keys.Up or LocaleKeycode == Keys.Down or LocaleKeycode == Keys.Right or LocaleKeycode == Keys.Left then
if KeysDown[LocaleKeycode] then return end
KeysDown[LocaleKeycode] = true
downCount += 1
if downCount > 1 then return end
repeat
if KeysDown[Keys.Up] then
ButtonToMove.Position += UDim2.fromScale(0,-MovementDistance)
end
if KeysDown[Keys.Down] then
ButtonToMove.Position += UDim2.fromScale(0,MovementDistance)
end
if KeysDown[Keys.Right] then
ButtonToMove.Position += UDim2.fromScale(MovementDistance,0)
end
if KeysDown[Keys.Left] then
ButtonToMove.Position += UDim2.fromScale(-MovementDistance,0)
end
task.wait(MovementInterval)
until downCount < 1
end
end)
UIS.InputEnded:Connect(function(input, gameprocessed)
if gameprocessed then return end
local LocaleKeycode = input.KeyCode
if LocaleKeycode == Keys.Up or LocaleKeycode == Keys.Down or LocaleKeycode == Keys.Right or LocaleKeycode == Keys.Left then
KeysDown[LocaleKeycode] = nil
downCount -= 1
end
end)