Hello! I’m trying to make a game similar to MGS3. part of that is wading through water, and crouching in water.
the problem I’m having, is roblox makes my character swim as soon as he crouches in the water. I understand the water is deep, but I don’t want the character to swim yet. it also causes issues just moving through the water, since sometimes his torso touches it.
External MediaI have a script that’s supposed to override this, but it isn’t working. any help is greatly appreciated !!
local RunService = game:GetService("RunService")
local SWIM_THRESHOLD_HEIGHT = -1
local function getTerrainWaterLevel(position)
local min = Vector3.new(
math.floor(position.X / 4) * 4 - 4,
math.floor(position.Y / 4) * 4 - 4,
math.floor(position.Z / 4) * 4 - 4
)
local max = Vector3.new(
math.ceil(position.X / 4) * 4 + 4,
math.ceil(position.Y / 4) * 4 + 4,
math.ceil(position.Z / 4) * 4 + 4
)
local region = Region3.new(min, max)
local material, occupancy = workspace.Terrain:ReadVoxels(region, 4)
local highestWaterY = nil
local size = material.Size
for x = 1, size.X do
for y = 1, size.Y do
for z = 1, size.Z do
if material[x][y][z] == Enum.Material.Water and occupancy[x][y][z] > 0 then
local worldY = min.Y + (y - 1) * 4
if not highestWaterY or worldY > highestWaterY then
highestWaterY = worldY
end
end
end
end
end
return highestWaterY
end
local function shouldCharacterSwim(character)
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
if not humanoidRootPart then return false end
local waterLevel = getTerrainWaterLevel(humanoidRootPart.Position)
local footLevel = humanoidRootPart.Position.Y - (humanoidRootPart.Size.Y / 2)
return waterLevel and (waterLevel - footLevel) >= SWIM_THRESHOLD_HEIGHT
end
local function manageSwimmingState(character)
local humanoid = character:FindFirstChild("Humanoid")
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
if not humanoid or not humanoidRootPart then return end
local shouldSwim = shouldCharacterSwim(character)
local currentState = humanoid:GetState()
local player = Players:GetPlayerFromCharacter(character)
if player then
print(player.Name .. " - ShouldSwim: " .. tostring(shouldSwim) .. " | CurrentState: " .. tostring(currentState))
end
if shouldSwim then
humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming, true)
if currentState ~= Enum.HumanoidStateType.Swimming then
humanoid:ChangeState(Enum.HumanoidStateType.Swimming)
end
else
humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming, false)
-- If we're currently swimming, force out of it
if currentState == Enum.HumanoidStateType.Swimming then
local raycast = workspace:Raycast(humanoidRootPart.Position, Vector3.new(0, -8, 0))
if raycast and raycast.Distance < 6 then
humanoid:ChangeState(Enum.HumanoidStateType.Running)
else
humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
end
end
end
end
local function setupCharacterSwimming(character)
local humanoid = character:WaitForChild("Humanoid")
humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming, false)
local connection
connection = RunService.Heartbeat:Connect(function()
if character.Parent then
manageSwimmingState(character)
else
connection:Disconnect()
end
end)
local stateConnection
stateConnection = humanoid.StateChanged:Connect(function(oldState, newState)
if not character.Parent then
stateConnection:Disconnect()
return
end
-- If somehow we got into swimming when we shouldn't
if newState == Enum.HumanoidStateType.Swimming and not shouldCharacterSwim(character) then
-- Immediately disable and change state
humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming, false)
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then
local raycast = workspace:Raycast(humanoidRootPart.Position, Vector3.new(0, -8, 0))
if raycast and raycast.Distance < 6 then
humanoid:ChangeState(Enum.HumanoidStateType.Running)
else
humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
end
end
end
end)
end
for _, player in pairs(Players:GetPlayers()) do
if player.Character then
setupCharacterSwimming(player.Character)
end
end
Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
setupCharacterSwimming(character)
end)
end)```