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:
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:
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.
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.
Setting the AssemblyLinearVelocity will keep making you move up with a mass amount of distance every second with your piece of code.
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).
For the BodyForce, parent it to the HumanoidRootPart
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.)
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.
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.
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)