Help with creating custom swimming system

How would I get started on coding a custom swimming system while still using roblox terrain? I would want it to be so you cannot swim down and are stuck at the top of the water, as all the custom movement mechanics and custom animations do not play well with roblox’s hard coded swimming system.

1 Like

You disable the default swimming, I cant off hand remember the api.
Then you raycast for water voxels, and apply an up force until you are at the top of the water.

After some research, is there a way I could modify the waters buoyancy? That is all I need to do.

How could I implement this into my game?

these resources can be helpful but here are some technical or examples ways you can use as a starting point maybe who knows…

You’ll need a script to detect when the character is underwater and activate/deactivate the BodyPosition. Here’s a basic example:

local function isInWater(part)
  -- Replace "waterPart" with your actual water part
  return part.Touching:FindFirstChild("waterPart") ~= nil
end

local function updateBuoyancy(humanoid)
  local isUnderwater = isInWater(humanoid.RootPart)
  bodyPosition.Enabled = isUnderwater
end

humanoid:GetPropertyChangedSignal("IsSwimming"):Connect(updateBuoyancy)

you can also edit the character density as roblox has it built-in i guess (buoyancy)

  • Access the character’s humanoid:
    local humanoid = script.Parent:FindFirstChild("Humanoid")

  • Loop through the character’s limbs:

for _, limb in pairs(humanoid:GetBodyParts()) do
  -- Set density for each limb
  limb.CustomPhysicalProperties = PhysicalProperties.new(density = desired_density)
end

BodyPosition for Surface Floating:

  1. Create a BodyPosition Object: A BodyPosition object applies a force to the character, trying to keep them at a specific position or orientation. In this case, you’ll use it to create an upward force when the character is underwater.
  • Set BodyPosition Properties:
local bodyPosition = Instance.new("BodyPosition")
bodyPosition.Parent = character.Torso --  You can attach it to any relevant part
bodyPosition.P = floatForce -- Adjust the upward force for desired buoyancy
bodyPosition.Position = targetWaterSurfacePosition -- Update this value to match the water surface

Doing that breaks jumping, I want to use roblox’s built in terrain system’s water (as it is already on my map and some mechanics rely on it), What I want to understand how to do is how to make it so the player is always forced on top on the water, Not standing, just make it so you cannot dive under, as my custom movement and animations break when in water.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

-- Adjust these values as needed
local waterSurfaceYPosition = 50 -- Example Y position of your water's surface
local upwardForceMagnitude = 50 -- Adjust based on testing for a natural feel

local function applyUpwardForce()
    if humanoid:GetState() == Enum.HumanoidStateType.Swimming then
        local currentPos = humanoidRootPart.Position
        -- Check if below the surface; if so, apply force or adjust position
        if currentPos.Y < waterSurfaceYPosition then
            -- Option 1: Apply an upward force to the HumanoidRootPart
            humanoidRootPart:ApplyImpulse(Vector3.new(0, upwardForceMagnitude, 0))
            
            -- Option 2: Directly adjust the position (uncomment to use instead)
            -- humanoidRootPart.Position = Vector3.new(currentPos.X, waterSurfaceYPosition, currentPos.Z)
        end
    end
end

-- Connect the function to the Heartbeat event for continuous checks
RunService.Heartbeat:Connect(applyUpwardForce)

-- Optional: Listen for the character being loaded in (e.g., after respawning)
player.CharacterAdded:Connect(function(newCharacter)
    character = newCharacter
    humanoid = newCharacter:WaitForChild("Humanoid")
    humanoidRootPart = newCharacter:WaitForChild("HumanoidRootPart")
end)

I guess you’ll adjust this based on your mechanics side or water and buoyancy effects !

Thank you for this, It worked but please do not do this again as it is not allowed under devforum rules to provide full scripts.

Got it but it worked for glad it helps