When this is happening the character is in a loop of:
Jumping
Freefall
Swimming
Jumping
This happens because the check to enter the swimming state and the check for preventing jumping while in water are slightly different.
The check to enter the swimming state just checks if the HumanoidRootPart is colliding with water, the same way part buoyancy is normally checked.
The check for jumping is a coarse check to see if the center of the HumanoidRootPart is in a water cell. This allows the character to ājumpā out of water when they are swimming on the surface.
For now as a workaround you can try disabling the Jumping state as soon as the Humanoid enters the Swimming state and re-enabling it when it leaves the Swimming state by landing or climbing out:
humanoid.StateChanged:Connect(function(old, new)
if new == Enum.HumanoidStateType.Swimming then
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
else
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
end
end)
Note that this would disable jumping out of water while swimming on the surface!
You could further mitigate that issue by adding a raycast check down from the center of the HumanoidRootPart to check for water surface while swimming, and enabling the Jumping state while thereās water surface below that center point.
This would let you jump while over water surface, but not with water in front of you.
Hereās an example you can drop in a LocalScript in StarterCharacterScripts that seems to work around the issues (Note: for simplicity it doesnāt safely handle the character being removed from workspace):
local RunService = game:GetService("RunService")
local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local steppedConnection = nil
humanoid.StateChanged:Connect(function(old, new)
if new == Enum.HumanoidStateType.Swimming then
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
steppedConnection = RunService.Stepped:Connect(function()
local part, point, normal, material = workspace:FindPartOnRay(Ray.new(humanoid.RootPart.Position, Vector3.new(0, -humanoid.HipHeight, 0)), character)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, part and material == Enum.Material.Water or false)
end)
else
humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
if steppedConnection then steppedConnection:Disconnect() steppedConnection = nil end
end
end)
Weāll have to think more about the cost/benefit of adding a check like this in Humanoid itself. Seems like we should, but Iām not sure what the risk of game breaking would be for a change like that yetā¦