Make Character Float, AssemblyLinearVelocity

Hello. I’m trying to make the player float by applying velocity on Y axis.

My issue is that it doesn’t seem to be too consistent and the force required to make the player float is very random.

Normally you’d get the entire mass of the character by looping through all base parts and then adding their mass to the total mass multiplied by the gravity like so:

local mass = 0

for _, object in pairs(player.Character:GetDescendants()) do
	if not object:IsA("BasePart") then
		continue
	end
	mass = mass + object.AssemblyMass * workspace.Gravity
end

And then apply the velocity to the HumanoidRootPart on every heartbeat:

RunService.Heartbeat:Connect(function()
	HRP.AssemblyLinearVelocity = Vector3.new(0, mass, 0)
end)

But what the above code does is fling the player into space for some reason
ezgif-5-1021cbd15c

I tried to apply the velocity based on the HumanoidRootPart’s AssemblyMass

RunService.Heartbeat:Connect(function()
	HRP.AssemblyLinearVelocity = Vector3.new(0, HRP.AssemblyMass, 0)
end)

but it was still too much:
ezgif-5-e1a032a38b

For clarity, HumanoidRootPart’s AssemblyMass is 2.4
And for some unknown reason, once I set the force to 2.1 it appears that the player is indeed floating:
ezgif-5-44750892cc

But it’s not perfect, the player is slowly accelerating upwards. I’m out of ideas as to how I could set the force correctly.

Any help is greatly appreciated.

  1. AssemblyMass takes in account of all connected BaseParts, which is why you were flying off to space. You were thinking of the other property called Mass.
  2. Setting the AssemblyLinearVelocity will keep making you move up with a mass amount of distance every second with your piece of code.
  3. Consider using AlignPosition with it’s Mode set to Enum.PositionAlignmentMode set to OneAttachment, ForceLimitMode set to PerAxis, and the MaxAxesForce set to Vector3.new(0, math.huge, 0).
1 Like

Yeah because what you calculated is the force, not the velocity you need.
You need to add an object which applies force for example BodyForce (there should be a replacement for this though).

  1. For the BodyForce, parent it to the HumanoidRootPart
  2. Set the BodyForce.Force to the above vector you used.
    (Also for this method you dont need to use heartbeat on it, instead set it once.)
1 Like

Don’t use AssemblyLinearVelocity, use a VectorForce. It’s the same thing, but it applies a constant amount of force upwards. You can calculate the amount of force wanted/needed and apply it without using a loop.

1 Like

creating a consistent floating effect:

local RunService = game:GetService("RunService")

local function makePlayerFloat(player)
	local HRP = player.Character:FindFirstChild("HumanoidRootPart")
	if not HRP then return end

	local totalMass = 0
	for _, part in pairs(player.Character:GetDescendants()) do
		if part:IsA("BasePart") then
			totalMass = totalMass + part.AssemblyMass
		end
	end

	local gravity = workspace.Gravity
	local antiGravityForce = totalMass * gravity

	RunService.Heartbeat:Connect(function()
		local currentVelocity = HRP.AssemblyLinearVelocity
		HRP.AssemblyLinearVelocity = Vector3.new(currentVelocity.X, antiGravityForce / totalMass, currentVelocity.Z)
	end)
end
  • apply just enough force to counteract gravity, not more

Set the LinearVelocity’s VelocityConstraintMode to Line, with LineDirection 0, 1, 0. And then set the LineVelocity to zero. Ensure ForceLimitsEnabled is set to false; and that should keep the character vertically locked, while still allowing for horizontal movement.

If you still intend for some verticality (allowing players to traverse inclines while floating), you could alternatively keep force limits in place, but set the MaxForce to some number in the general ballpark of AssemblyMass * Gravity. The advantage of this approach, being that you wouldn’t need to bother about being too exact, so long as you maintain an excess of MaxForce rather than a deficit.

What are you looking to do? Just go up a bit and float and then back down.

To make the character float and maintain a consistent height effortlessly, you need to create a more dynamic solution that adjusts the character’s vertical velocity based on their current height.

local RunService = game:GetService("RunService")
local player = game.Players.LocalPlayer -- Or however you're getting the player reference

-- Target height above the ground
local targetHeight = 5 -- Change this to whatever height you want

RunService.Heartbeat:Connect(function()
    local HRP = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
    if not HRP then return end

    local ray = Ray.new(HRP.Position, Vector3.new(0, -targetHeight - 5, 0)) -- Cast a ray downward
    local hit, position = workspace:FindPartOnRay(ray, player.Character)

    if hit then
        local currentHeight = (HRP.Position - position).magnitude
        local heightDifference = targetHeight - currentHeight

        -- Proportional control factor (tweak this value to get the desired responsiveness)
        local k = 50 -- This value might need tuning based on testing

        -- Calculate the adjustment needed. Add workspace.Gravity to counteract gravity's pull
        local velocityAdjustment = k * heightDifference + workspace.Gravity

        -- Apply this adjustment to the character
        HRP.AssemblyLinearVelocity = Vector3.new(0, velocityAdjustment, 0)
    else
        -- If not over anything, just apply a force to counteract gravity
        HRP.AssemblyLinearVelocity = Vector3.new(0, workspace.Gravity, 0)
    end
end)

Ohhh completely forgot about Linear constraints!

Yup, LinearVelocity constraint seems to do the trick.

Thank you and everybody who engaged in this post!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.