Is there a way to temporarily take out BodyGyro + Velocity?

Hello! I have a script that makes the player move along rails using BodyVelocity + BodyGyro and the script itself works very well.

However, there is an issue when it comes to the slide function – The BodyGyro and BodyVelocity from this script seems to make the slide function from another script not work. The slide itself uses a BodyVelocity too so I’m thinking that all the BGs and BVs are colliding with each other causing issues.

Is there a fix for this? If needed for extra context I can also include the slide script.

Any help will be greatly appreciated, and I thank you in advance!

local player = game:GetService("Players").LocalPlayer
local runService = game:GetService("RunService")
local userInputService = game:GetService("UserInputService")
local speedMultiplier = 1

local rail = nil
local isOnPath = false
local lastPath = nil
local pathStartTime = 0
local pathSpeed = 0
local pathXOffset = 0

local jumpTime = 0

local bodyVelocity, bodyGyro

userInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if not gameProcessedEvent and player.Character then
		local keyCode = input.KeyCode
		local character = player.Character

		if keyCode == Enum.KeyCode.Space then
			if rail ~= nil then
				jumpTime = tick()
				rail = nil
				isOnPath = false
				bodyVelocity.MaxForce = Vector3.new(0, 0, 0)
				bodyGyro.MaxTorque = Vector3.new(0, 0, 0)
				character:WaitForChild("Humanoid").PlatformStand = false
				character:WaitForChild("Humanoid"):ChangeState(Enum.HumanoidStateType.Jumping)
				character:WaitForChild("HumanoidRootPart").Velocity = character:WaitForChild("HumanoidRootPart").Velocity + character:WaitForChild("HumanoidRootPart").CFrame.UpVector * 50

				character:WaitForChild("HumanoidRootPart").CFrame = CFrame.new(
				character:WaitForChild("HumanoidRootPart").Position,
				character:WaitForChild("HumanoidRootPart").Position + (character:WaitForChild("HumanoidRootPart").Velocity - Vector3.new(0, character:WaitForChild("HumanoidRootPart").Velocity.Y, 0))
				)
			end
		end
	end
end)

function onRails(railObject)
	if (railObject ~= rail or rail == nil) and player.Character then
		local character = player.Character

		if rail == nil then
			local speedMultiplier = 1
			local velocityMagnitude = character.HumanoidRootPart.Velocity.Magnitude
			local speedDif = math.max((velocityMagnitude - 80) / 75, 0)
			speedMultiplier = 1 + speedDif
			print(speedMultiplier)
		end

		rail = railObject

		bodyVelocity.MaxForce = Vector3.new(10000, 10000, 10000)
		bodyGyro.MaxTorque = Vector3.new(100000, 100000, 100000)
		bodyGyro.CFrame = rail.CFrame
		character.Humanoid.PlatformStand = true

		if rail ~= nil then
			local xOffset = rail.CFrame:pointToObjectSpace(character.HumanoidRootPart.CFrame.Position).X
			pathXOffset = xOffset
			local zOffset = rail.CFrame:pointToObjectSpace(character.HumanoidRootPart.CFrame.Position).Z
			local rotation = character.HumanoidRootPart.CFrame - character.HumanoidRootPart.CFrame.Position
			character.HumanoidRootPart.CFrame = CFrame.new((rail.CFrame * CFrame.new(xOffset, 3, zOffset)).Position) * rotation
			character.HumanoidRootPart.Velocity = CFrame.new(
				character.HumanoidRootPart.Position,
				rail.CFrame * CFrame.new(0, 3, -rail.Size.Z / 2 - 2).Position
			).LookVector * (80 * speedMultiplier)
			bodyVelocity.Velocity = CFrame.new(
				character.HumanoidRootPart.Position,
				rail.CFrame * CFrame.new(0, 3, -rail.Size.Z / 2 - 2).Position
			).LookVector * (80 * speedMultiplier)
		end
	end
end

local railsFolder = workspace:WaitForChild("Other +"):WaitForChild("Rails")

function bindPart(obj)
	obj.Touched:Connect(function(part)
		if tick() - jumpTime > 1 then
			if part:IsDescendantOf(railsFolder) then
				onRails(part)
			end
		end
	end)
end

function characterAdded(character)
	repeat wait() until character.Parent ~= nil
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

	bodyVelocity = Instance.new("BodyVelocity", humanoidRootPart)
	bodyGyro = Instance.new("BodyGyro", humanoidRootPart)
	bodyVelocity.MaxForce = Vector3.new(0, 0, 0)
	bodyGyro.MaxTorque = Vector3.new(0, 0, 0)
	bodyGyro.D = 50

	local speedMultiplier = 1

	character.Humanoid.Changed:Connect(function(property)
		if property == "Jump" and character.Humanoid.Jump == true and rail ~= nil then
			character.Humanoid.Jump = false
		end
	end)

	character.ChildAdded:Connect(function(part)
		if part:IsA("BasePart") then
			bindPart(part)
		end
	end)

	for _, part in pairs(character:GetChildren()) do
		if part:IsA("BasePart") then
			bindPart(part)
		end
	end
end

player.CharacterAdded:Connect(characterAdded)

if player.Character then
	characterAdded(player.Character)
end

local lastTime = tick()
runService:BindToRenderStep("RailGrinding", Enum.RenderPriority.Character.Value, function()
	local deltaTime = (tick() - lastTime) * 60
	lastTime = tick()

	if rail ~= nil and player.Character then
		local character = player.Character

		if ((character.HumanoidRootPart.Position - (rail.CFrame * CFrame.new(pathXOffset, 2.5, -rail.Size.Z / 2 - 2).Position)).Magnitude < 4 or
			(character.HumanoidRootPart.Position - rail.Position).Magnitude > rail.Size.Z + 2) or
			(isOnPath == true and character:WaitForChild("Humanoid").MoveDirection.Magnitude < 0.5) then
			pathStartTime = tick()
			lastPath = rail
			rail = nil
			isOnPath = false
			bodyVelocity.MaxForce = Vector3.new(0, 0, 0)
			local oldGyro = bodyGyro.CFrame

			delay(0.025, function()
				if bodyGyro.CFrame == oldGyro then
					bodyGyro.MaxTorque = Vector3.new(0, 0, 0)
					character:WaitForChild("Humanoid").PlatformStand = false
				end
			end)
		else
			if isOnPath then
				bodyGyro.CFrame = rail.CFrame
				character.HumanoidRootPart.Velocity = CFrame.new(
					character.HumanoidRootPart.Position,
					rail.CFrame * CFrame.new(pathXOffset, 3, -rail.Size.Z / 2 - 2).Position
				).LookVector * pathSpeed
				bodyVelocity.Velocity = CFrame.new(
					character.HumanoidRootPart.Position,
					rail.CFrame * CFrame.new(pathXOffset, 3, -rail.Size.Z / 2 - 2).Position
				).LookVector * pathSpeed
			else
				bodyGyro.CFrame = rail.CFrame
				character.HumanoidRootPart.Velocity = CFrame.new(
					character.HumanoidRootPart.Position,
					rail.CFrame * CFrame.new(0, 3, -rail.Size.Z / 2 - 2).Position
				).LookVector * (80 * speedMultiplier)
				bodyVelocity.Velocity = CFrame.new(
					character.HumanoidRootPart.Position,
					rail.CFrame * CFrame.new(0, 3, -rail.Size.Z / 2 - 2).Position
				).LookVector * (80 * speedMultiplier)

				if math.sign(bodyVelocity.Velocity.Y) < 0 then
					if speedMultiplier < 2 then
						speedMultiplier = math.min(speedMultiplier + ((1 / 60) * deltaTime), 2)
					end
				else
					if speedMultiplier > 1 then
						speedMultiplier = math.max(speedMultiplier - ((1 / 60) * deltaTime), 1)
					end
				end

				if speedMultiplier > 2 then
					speedMultiplier = math.min(speedMultiplier - (speedMultiplier / 32), 2)
				end
			end
		end
	end
end)
1 Like

Why don’t you use a LinearVelocity instead of a BodyVelocity? BodyVelocity is deprecated and LinearVelocity has an Enabled property (inherited from Constraint).

1 Like

I’m not really sure how to get the attachments to work out, plus from what I can tell I would probably have to change how the rails work

Gave it a shot, and sadly linearvelocity didn’t work out :pensive: