Unwanted + 'Sticking' controller behavior with custom swimming

Hello everyone!

Although terrain water is nice, Ive decided to work on water movement for normal parts. I have gotten that part to work, so that isn’t the issue. This issue started when I brought controller support up to the table.

My goal was to bring controller support. Seems easy enough? What I thought. Maybe im overlooking it. My goal was to add support for controllers by binding RT(ButtonR2), and A (ButtonA) to up and down movements. These are still a bit finicky though. The Thumbstick has also been causing a lot of trouble. The animations have been flickery between Idle and moving, because I can’t seem to find a good reliable way to determine whether the Thumbstick is in the center rest position or not.

Besides the visual errors, there’s also an important bug I haven’t been able to solve. If a user is holding LShift on a keyboard to go down, they are able to press Space to go up, and then remove space and continue going down. With controllers I find it weird, but it isn’t able to connect like that.

I have tried manually detecting inputs, which I later ditched because its much easier to compare the velocity of the BodyVelocity to which direction they are to go in, but this isn’t the case for idle and normal movement.

*I put a simple GUI in the bottom right so you can see what inputs are being used when to make it easier to understand.

devforum yet again wont let me upload files, so here’s the imagur links

This is the behavior with a keyboard. This is how I want console to be like:

This is the current console behavior. It sticks, and the animations aren’t right:

Heres the code behind it

local cS = game:GetService("CollectionService")
local uIS = game:GetService("UserInputService")
local character = workspace:WaitForChild(game.Players.LocalPlayer.Name)
debounce = false
local camera = workspace.CurrentCamera
local swimming = false

local current = 0

local humanoid = character:WaitForChild("Humanoid")
local swimIdle = Instance.new("Animation")
swimIdle.Parent = humanoid
local swimUp = Instance.new("Animation")
swimUp.Parent = humanoid
local swimNormal = Instance.new("Animation")
swimNormal.Parent = humanoid
local swimDown = Instance.new("Animation")
swimDown.Parent = humanoid
local jump = Instance.new("Animation")
jump.Parent = humanoid
jump.AnimationId = "rbxassetid://5029062334"
swimDown.AnimationId = "rbxassetid://5327772527"
swimNormal.AnimationId = "rbxassetid://5327766201"
swimUp.AnimationId = "rbxassetid://5327770174"
swimIdle.AnimationId = "rbxassetid://5327865179"
local swimIdleAnim = humanoid:LoadAnimation(swimIdle)
local swimUpAnim = humanoid:LoadAnimation(swimUp)
local swimNormalAnim = humanoid:LoadAnimation(swimNormal)
local swimDownAnim = humanoid:LoadAnimation(swimDown)
local jumpAnim = humanoid:LoadAnimation(jump)

local velocity = Instance.new("BodyVelocity")
velocity.Parent = nil
velocity.MaxForce = Vector3.new(0,13000,0)
velocity.P = 7500
velocity.Velocity = Vector3.new(0,-.1,0)

local gamePad = Enum.UserInputType.Gamepad1

local downTween = game:GetService("TweenService"):Create(velocity,TweenInfo.new(.625),{velocity = Vector3.new(0,-.1,0)})

local particles = script.Bubbles

function animate(key)
	if swimming == true and uIS:IsKeyDown(Enum.KeyCode.W) or uIS:IsKeyDown(Enum.KeyCode.A) or uIS:IsKeyDown(Enum.KeyCode.S) or uIS:IsKeyDown(Enum.KeyCode.D) or uIS:IsKeyDown(Enum.KeyCode.Space) or uIS:IsKeyDown(Enum.KeyCode.LeftShift) or key.KeyCode == Enum.KeyCode.ButtonA or key.KeyCode == Enum.KeyCode.ButtonR2 or key.KeyCode == Enum.KeyCode.Thumbstick1  then
		if swimming == true then
			if velocity.Velocity == Vector3.new(0,20,0) then
				if current ~= 2 then
					current = 2
					swimNormalAnim:Stop()
					swimIdleAnim:Stop()
					swimDownAnim:Stop()
					swimUpAnim:Play()
				end
			elseif velocity.Velocity == Vector3.new(0,-20,0) then
				if current ~= 4 then
					current = 4
					swimNormalAnim:Stop()
					swimIdleAnim:Stop()
					swimUpAnim:Stop()
					swimDownAnim:Play()
				end
				
			elseif uIS:GetLastInputType() == Enum.UserInputType.Gamepad1 and math.abs(key.Position.Magnitude) < .16 and velocity.Velocity == Vector3.new(0,-.1,0) and key.KeyCode == Enum.KeyCode.Thumbstick1 or uIS.GamepadConnected and uIS:IsGamepadButtonDown(gamePad,Enum.KeyCode.Thumbstick1) then
				if current ~= 1 then
					current = 1
					swimUpAnim:Stop()
					swimDownAnim:Stop()
					swimNormalAnim:Stop()
					swimIdleAnim:Play()
				end
			else
				if current ~= 3 then
					current = 3
					swimIdleAnim:Stop()
					swimUpAnim:Stop()
					swimDownAnim:Stop()
					swimNormalAnim:Play()
				end
			end
		end
	else
		if swimming == true then
			if current ~= 1 then
				current = 1
				swimUpAnim:Stop()
				swimDownAnim:Stop()
				swimNormalAnim:Stop()
				swimIdleAnim:Play()
			end
		end
	end	
end



function isInsidePart(part,Pos)
  -- not issue
end



local function swim(waterPart)
   -- not the issue
end

wait(1)

for i,v in pairs(cS:GetTagged("partWater")) do
	swim(v)
end


uIS.InputBegan:Connect(function(key)
	if velocity.Velocity ~= Vector3.new(0,28,0) then -- This check is to remove the edge case where if you swam down right as you left it would glitch out. 
		if key.KeyCode == Enum.KeyCode.LeftShift or key.KeyCode == Enum.KeyCode.ButtonR2 then
			downTween:Cancel()
			velocity.Velocity = Vector3.new(0,-20,0)
		elseif key.KeyCode == Enum.KeyCode.Space or key.KeyCode == Enum.KeyCode.ButtonA then
			downTween:Cancel()
			velocity.Velocity = Vector3.new(0,20,0)
		end
		
		animate(key)
	end
end)

uIS.InputChanged:Connect(function(key)
	if uIS.GamepadConnected and velocity.Velocity ~= Vector3.new(0,28,0) then
		if key.KeyCode == Enum.KeyCode.LeftShift or key.KeyCode == Enum.KeyCode.Space or key.KeyCode == Enum.KeyCode.ButtonR2 or key.KeyCode == Enum.KeyCode.ButtonA then
			if key.KeyCode == Enum.KeyCode.LeftShift or key.KeyCode == Enum.KeyCode.ButtonR2 then
				if uIS:IsKeyDown(Enum.KeyCode.Space) or key.KeyCode == Enum.KeyCode.ButtonA then
					velocity.Velocity = Vector3.new(0,20,0)
				else
					velocity.Velocity = Vector3.new(0,-.1,0)
				end
			elseif key.KeyCode == Enum.KeyCode.Space or key.KeyCode == Enum.KeyCode.ButtonA then
				if uIS:IsKeyDown(Enum.KeyCode.LeftShift) or key.KeyCode == Enum.KeyCode.ButtonR2 then
					velocity.Velocity = Vector3.new(0,-20,0)
				else
					velocity.Velocity = Vector3.new(0,-.1,0)
				end
			else
				velocity.Velocity = Vector3.new(0,-.1,0)
			end
		end
		
		animate(key)
	end
end)

uIS.InputEnded:Connect(function(key)
	if velocity.Velocity ~= Vector3.new(0,28,0) then
		if key.KeyCode == Enum.KeyCode.LeftShift or key.KeyCode == Enum.KeyCode.Space or key.KeyCode == Enum.KeyCode.ButtonR2 or key.KeyCode == Enum.KeyCode.ButtonA then
			if key.KeyCode == Enum.KeyCode.LeftShift or key.KeyCode == Enum.KeyCode.ButtonR2 then
				if uIS:IsKeyDown(Enum.KeyCode.Space) or key.KeyCode == Enum.KeyCode.ButtonA then
					velocity.Velocity = Vector3.new(0,20,0)
				else
					velocity.Velocity = Vector3.new(0,-.1,0)
				end
			elseif key.KeyCode == Enum.KeyCode.Space or key.KeyCode == Enum.KeyCode.ButtonA then
				if uIS:IsKeyDown(Enum.KeyCode.LeftShift) or key.KeyCode == Enum.KeyCode.ButtonR2 then
					velocity.Velocity = Vector3.new(0,-20,0)
				else
					velocity.Velocity = Vector3.new(0,-.1,0)
				end
			else
				velocity.Velocity = Vector3.new(0,-.1,0)
			end
		end
		
		animate(key)
	end
end)

game:GetService("RunService").Heartbeat:Connect(function()
	local camInside = false
	for i,v in pairs(game:GetService("CollectionService"):GetTagged("partWater")) do
		if isInsidePart(v,camera.CFrame.Position) then
			camInside = true
			continue
		end	 
	end
	waterGui.Enabled = camInside
end)

Thanks to anyone whos able to help me with this! Im not sure what else I should do with this.
-grif

Maybe because you aren’t detecting if it is being held down and you’re checking instead if it was pressed so it constantly holds it?

You are detecting IsKeyDown with keyboard, but not doing the same style with controllers.

I was initially using IsGamepadButtonDown but that was also weird. The Thumbstick check is also pretty weird. Writing this I can already see one thing Ive done but im still unsure about the Thumbstick, as it still acts up sometimes. Its hard to show without a like 3 minute video though.

EDIT: Tried re-adding IsGamepadButtonDown, but the same behavior is happening while checking the keycode and for IsGamepadButtonDown, so im not sure about that