Hovering platform that moves depending on mass

Hello!

To begin with, I would like to apologize if the category of this post is not correct. I am not 100% sure if I should place this in Building Support or Scripting Support as it might require both of them.

For the past few days, I was trying to create a levitating platform that you would stand on and it will move depending on which part of the platform is heavier. Here’s an example of what it should look like: Roblox Anakin Vs Obi-Wan (Lava Pad Battle) Roblox Lightsaber Battlegrounds / Roblox Ilum 2 - YouTube

I had some progress with making a part levitate, but it was very buggy (it would not return to its starter rotation/orientation if it is not straight, and when the player stands on it, it would slowly fall down although I’m calculating the players’ weight in the script as well). Also, I’m not really sure how I would make it move depending on where the player stands, would hitboxes work or there is a way to find where the mass is higher?

Here is the script I used. It works, but it doesn’t seem to calculate the player’s mass correctly so when a player stands on the part, the part starts going down slowly or bugs.

game:GetService("RunService").Heartbeat:Connect(function()
local totalMass = totalMass -- Keep a temporary copy of totalMass so it can be modified
local partsCounted = {}
				
	local function check(part)
		local human = part.Parent:FindFirstChildOfClass("Humanoid")
			if human then
				if human:GetLimb(part) ~= Enum.Limb.Unknown then
					part = human.RootPart
					if check(part) then
						partsCounted[part] = true
						totalMass = totalMass + part:GetMass()
					end
					return false
				end
			end
					
			return not part.Massless and not partsCounted[part] and not script.Parent:IsAncestorOf(part) and not part:IsGrounded()
		end
				
		for _, part in ipairs(hitbox:GetTouchingParts()) do
			if check(part) then
				partsCounted[part] = true
				totalMass = totalMass + part:GetMass()
						
				for _, part in ipairs(part:GetConnectedParts(true)) do
					if check(part) then
						partsCounted[part] = true
						totalMass = totalMass + part:GetMass()
					end
				end
			end
		end
				
		local ray = Ray.new(thruster.CFrame.p, Vector3.new(0, -1000, 0))
		local ignore = {script.Parent}
		local hit, pos, norm = workspace:FindPartOnRayWithIgnoreList(ray, ignore)
				
		if not hit then
			return
		end
				
		while not hit.CanCollide do
			table.insert(ignore, hit)
			hit, pos, norm = workspace:FindPartOnRayWithIgnoreList(ray, ignore)
			if not hit then
				return
			end
		end
				
		local dist = (thruster.CFrame.p-pos).Magnitude-targetHeight.Value
				
		if gyro then
			gyro.CFrame = CFrame.new(Vector3.new(), norm)*CFrame.Angles(math.rad(-90), 0, 0)
		end
				
		local antiGravity = workspace.Gravity * totalMass/numThrusters
		if automaticThrust then
			thrust.Value = antiGravity * 2^-stability.Value
		end
				
		local forceMask = Vector3.new(0, ((math.abs(dist) <= targetHeight.Value) and 1) or 0, 0)
		local thrustForce = thrust.Value - thrust.Value / ((dist/targetHeight.Value)^2)
		ThrustForce = math.sign(dist) * math.sign(thrustForce) * math.min(math.abs(thrustForce), thrust.Value*2) -- Make sure force isn't too large
				
		thrustForce = thrustForce + antiGravity -- Add anti gravity force
		force.Force = forceMask*thrustForce
		thruster.Velocity = thruster.Velocity*damping.Value
	end)

You could use this simple hover model, which calculates a force needed to push off the ground with an offset by getting the surface normal to the model itself, you’ll have to do some tweaking yourself, but this for the most part should be a good place to start, maybe? :thinking:

https://www.roblox.com/library/1456381316/Simple-Hover