BodyForce glitching when colliding with parts - how to fix?

I’ve been making a script for my Roblox game named Rebuild, where you can fly. Most things work fine, except for one singular thing. If I go down onto the floor, go up on the roof, or sometimes go onto the wall., my character will glitch out and fling me.

Blockate, Rebuild’s inspiration, simply doesn’t fling somehow. Like, if I go on the floor, it’ll allow me to move in all directions but not down, slightly hovering over the floor.

How could I fix my issue?

local players = game:GetService("Players")
local userinputservice = game:GetService("UserInputService")
local runservice = game:GetService("RunService")
local player = players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local rootpart = char:WaitForChild("HumanoidRootPart")
local defaultwalkspeed = humanoid.WalkSpeed
local defaultjumppower = humanoid.JumpPower
local flyenabled = false
local spaceheld = false
local shifthheld = false
local lastpress = 0
local doublepressdelay = 0.25
local bodypos = Instance.new("BodyPosition")
bodypos.MaxForce = Vector3.new(0, 0, 0)
bodypos.P = 10000
bodypos.D = 1000
bodypos.Position = rootpart.Position
bodypos.Parent = rootpart
local camera = workspace.CurrentCamera
local bodygyro = Instance.new("BodyGyro")
bodygyro.MaxTorque = Vector3.new(0, 0, 0)
bodygyro.P = 5000
bodygyro.D = 500
bodygyro.Parent = rootpart
bodygyro.CFrame = rootpart.CFrame
local legsupport = Instance.new("Part")
legsupport.Name = "flypartsupport"
legsupport.Anchored = true
legsupport.CanCollide = false
legsupport.Transparency = 1
legsupport.Size = Vector3.new(4, 0.1, 4)
legsupport.Parent = workspace.Client
legsupport.CanCollide = true
local flypart = game.ReplicatedStorage.Files.FlyPart:Clone()
flypart.Anchored = true
flypart.CanCollide = false
flypart.Transparency = 1
flypart.Size = Vector3.new(2, 1, 2)
flypart.Parent = workspace.Client
flypart.CanCollide = false
flypart.Position = Vector3.new(0, -math.huge, 0)
if not legsupport.CustomPhysicalProperties then
	legsupport.CustomPhysicalProperties = PhysicalProperties.new(1, 0.3, 0.5, 1, 1)
end
local currentprops = legsupport.CustomPhysicalProperties
legsupport.CustomPhysicalProperties = PhysicalProperties.new(
	currentprops.Density,
	0,
	currentprops.Elasticity,
	10,
	currentprops.ElasticityWeight
)
local allowedtotoggle = true
local function togglefly(val)
	if allowedtotoggle == false then return end
	flyenabled = val or not flyenabled
	if flyenabled then
		defaultwalkspeed = humanoid.WalkSpeed
		defaultjumppower = humanoid.JumpPower
		bodypos.Position = rootpart.Position
		bodypos.MaxForce = Vector3.new(0, math.huge, 0)
		humanoid.WalkSpeed = 50
		humanoid.JumpPower = 0
		flypart.ParticleEmitter.Enabled = true
	else
		bodypos.MaxForce = Vector3.new(0, 0, 0)
		humanoid.WalkSpeed = defaultwalkspeed
		humanoid.JumpPower = defaultjumppower
		legsupport.Position = Vector3.new(0, -1000, 0)
		flypart.ParticleEmitter.Enabled = false
		flypart.Position = Vector3.new(0, -math.huge, 0)
	end
	bodygyro.MaxTorque = flyenabled and Vector3.new(0, 50000, 0) or Vector3.new(0, 0, 0)
end
userinputservice.InputBegan:Connect(function(input, ischatting)
	if ischatting then return end

	if input.KeyCode == Enum.KeyCode.Space then
		local now = tick()
		if now - lastpress <= doublepressdelay then
			togglefly()
		elseif flyenabled then
			spaceheld = true
		end
		lastpress = now

	elseif input.KeyCode == Enum.KeyCode.LeftShift and flyenabled then
		shifthheld = true
	end
end)
userinputservice.InputEnded:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.Space then
		spaceheld = false
	elseif input.KeyCode == Enum.KeyCode.LeftShift then
		shifthheld = false
	end
end)
runservice.Heartbeat:Connect(function(dt)
	if not flyenabled then return end
	local deltay = 0
	if spaceheld then deltay += 30 * dt end
	if shifthheld then deltay -= 30 * dt end
	bodypos.Position = Vector3.new(rootpart.Position.X, bodypos.Position.Y + deltay, rootpart.Position.Z)
	local camlookvector = camera.CFrame.LookVector
	local oppositelook = Vector3.new(camlookvector.X, 0, camlookvector.Z).Unit
	local facecframe = CFrame.new(rootpart.Position, rootpart.Position + oppositelook)
	bodygyro.CFrame = facecframe
	legsupport.Position = rootpart.Position - Vector3.new(0, 1.75, 0)
	flypart.Position = rootpart.Position - Vector3.new(0, 3.5, 0)
end)
player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyOptions.Up.MouseButton1Down:Connect(function()
	spaceheld = true
	player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyOptions.Up.MouseButton1Up:Once(function()
		spaceheld = false
	end)
end)
player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyOptions.Down.MouseButton1Down:Connect(function()
	shifthheld = true
	player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyOptions.Down.MouseButton1Up:Once(function()
		shifthheld = false
	end)
end)
userinputservice.TouchStarted:Connect(function()
	player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyToggle.Visible = true
end)
local mouse = player:GetMouse()
mouse.Move:Connect(function()
	if userinputservice.TouchEnabled == false then
		player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyToggle.Visible = false
	end
end)
player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyToggle.MouseButton1Click:Connect(function()
	togglefly()
	if flyenabled then
		player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyToggle.Image =
			"rbxthumb://type=Asset&w=768&h=432&id=119898009410772"
		player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyOptions.Visible = true
	else
		player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyToggle.Image =
			"rbxthumb://type=Asset&w=768&h=432&id=98974847238544"
		player.PlayerGui.UserGUIHandler.Windows.MobileButtons.FlyOptions.Visible = false
	end
end)
game.ReplicatedStorage.Files.Events.StopBuilding.OnClientEvent:Connect(function()
	togglefly(false)
	allowedtotoggle = false
	flypart:Destroy()
	legsupport:Destroy()
	bodypos:Destroy()
	bodygyro:Destroy()
end)
1 Like

Because BodyPosition fights with collisions. To avoid this try add a raycast beneath the player to fix it. Push them up a little and give them zero vertical velocity if they’re too near the ground. This prevents physics bugs and keeps them stable.

1 Like

Another potential solution or even additional solution to remove velocity is to temporarily anchor/unanchor the Character Model’s PrimaryPart.
BodyPosition physics are often not fun to deal with though xd

update:

local debugpart = Instance.new("Part")
debugpart.Anchored = true
debugpart.Parent = game.Workspace.Client
debugpart.CanCollide = false
local function tooclose()
	local origin = rootpart.Position
	local direction = Vector3.new(0, -5, 0)
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Exclude
	params.FilterDescendantsInstances = {workspace.Client, char, workspace.Filter}
	params.IgnoreWater = true

	local midpoint = origin + direction / 2
	debugpart.CFrame = CFrame.new(midpoint, origin)
	debugpart.Size = Vector3.new(1, direction.Magnitude, 1)
	debugpart.Material = Enum.Material.Neon
	debugpart.Transparency = 0.5

	local raycastResult = workspace:Raycast(origin, direction, params)
	return raycastResult ~= nil
end
runservice.Heartbeat:Connect(function(dt)
	if not flyenabled then return end
	tooclose()
	local deltay = 0
	if spaceheld then
		deltay += 30 * dt
	elseif shifthheld and tooclose() == false then
		deltay -= 30 * dt
	elseif shifthheld and tooclose() == true then
		deltay = 0
		warn("YYY")
	end
	bodypos.Position = Vector3.new(rootpart.Position.X, bodypos.Position.Y + deltay, rootpart.Position.Z)
	local camlookvector = camera.CFrame.LookVector
	local oppositelook = Vector3.new(camlookvector.X, 0, camlookvector.Z).Unit
	bodygyro.CFrame = CFrame.new(rootpart.Position, rootpart.Position + oppositelook)

	legsupport.Position = rootpart.Position - Vector3.new(0, 1.75, 0)
	flypart.Position = rootpart.Position - Vector3.new(0, 3.5, 0)
end)

i have the raycast working, but if i go too close the ground and my vertical velocity is too fast, it’ll not slow down in time and still collide a little

1 Like

Since BodyPosition doesn’t directly cancel velocity, your character can still slam into the ground if falling too fast. To fix that manually zero or reduce vertical velocity when you’re too close to prevent the collision.

Add this inside your runservice.Heartbeat block after tooclose() is called and before updating bodypos.Position:

if tooclose() and rootpart.Velocity.Y < -5 then
	rootpart.Velocity = Vector3.new(rootpart.Velocity.X, 0, rootpart.Velocity.Z)
end

This stops fast downward movement when near the ground kind of like an emergency brake.

2 Likes

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