I can't properly transition between swimming and walking

I’m currently creating my own controller for a game, and was working on the swimming part of the controller. I have the swimming part and state handling done, but the transition is very odd. Here’s how i want it to behave:

When the character walks into water, as long as it touches the ground beneath the water (near the shore or just very shallow) it doesn’t switch to the swimming state. since i made the density of the character lower than the water, as it goes into deeper into the water it will float, and once it gets into the point where it no longer touches the ground, thats when it switches to the swimming state, and will stay there until it touches ground again.

heres the code snippet in the state machine that handles the swimming/running state (it runs every frame):

    local rootPart = character:WaitForChild("HumanoidRootPart")
	local currentState = humanoid:GetState()
	local isGrounded = groundSensor.SensedPart
	local isInWater = buoyancySensor.TouchingSurface

	-- Handle sitting first
	if humanoid.Sit then
		humanoid:ChangeState(Enum.HumanoidStateType.Seated)
		return
	end
	--print(b)
	-- Swimming logic - only enter swimming if in water AND not touching ground
	if isInWater and not isGrounded then
		if currentState ~= Enum.HumanoidStateType.Swimming then
			humanoid:ChangeState(Enum.HumanoidStateType.Swimming)
		end
		return
	end

	-- Exit swimming if touching ground (even if still in water)
	if currentState == Enum.HumanoidStateType.Swimming and isGrounded then
		humanoid:ChangeState(Enum.HumanoidStateType.Running)
		return
	end

heres the code snippet that handles the controller:

humanoid.StateChanged:Connect(function(old, new)
			if old == Enum.HumanoidStateType.Seated then
				self:SetBehavior("Ground")
				Inputs.EnableSeatExit(false)
			end

			if new == Enum.HumanoidStateType.Running then
				self:SetBehavior("Ground")
				controller.ActiveController = controller.GroundController
			elseif new == Enum.HumanoidStateType.Freefall then
				-- self:SetBehavior("Air")
				controller.ActiveController = controller.AirController
			elseif new == Enum.HumanoidStateType.Seated then
				self:DisableCurrentBehavior()
				Player.Character:SetAttribute("Sprinting", false)
				Player.Character:SetAttribute("Aiming", false)
				Inputs.EnableSeatExit(true)
			elseif new == Enum.HumanoidStateType.Swimming then
				self:SetBehavior("Water")
				controller.ActiveController = controller.SwimController
			end
		end)

the SetBehavior() function just switches how the player inputs are converted into movement.

my issue is that when the player walks into water, at a point it just stops moving and stays stuck in position. the state is still in the running state and only switches to swimming when i jump. also when im swimming and go back to shore, when i switch back to running, my character’s moves very slowly and speeds up as the water gets shallower.

heres a video showcasing this:

how do i fix this so that it transitions smoothly, and also fix that speed issue when walking out of water?

Im using the controller manager/physics-based controller instead of the old controller btw.

1 Like