How do I make this sliding system less janky

as you can see:
whenever i bump into a wall i completely lose control of the movement and it just pushes me in the same direction making me stuck,
when i only hold the key C, the game will start making me move around in a circle

if i also hit something my character will STRAIGHT UP get flung

code: (server)

local Folder = script.Parent
local RemoteEvent = Folder.RemoteEvent

local Players = game:GetService('Players')
local TweenService = game:GetService('TweenService')

local SlideThreads = {}
local SprintThreads = {}
local Instances = {}
RemoteEvent.OnServerEvent:Connect(function(player, command)
	local Character = player.Character
	local RootPart : BasePart = Character:FindFirstChild("HumanoidRootPart")
	local Humanoid = Character:FindFirstChildOfClass("Humanoid")
	if command == "SlideStart" then
		Character:SetAttribute("Sliding", true)
		SlideThreads[Character] = {}
		Instances[Character] = {
			Multiplier1 = nil,
			Multiplier2 = nil,
			Velocity = nil,
			Animation = nil,
		}
		
		local MainThread = task.spawn(function()
			Humanoid.CameraOffset = Vector3.new(0,-2,0)
			local Multiplier = Instance.new("NumberValue")
			local SlopeMultiplier = Instance.new("NumberValue")
			local Speed = 70
			local Velocity = Instance.new("BodyVelocity")
			Velocity.MaxForce = Vector3.new(1, 0, 1)*17000
			Velocity.Parent = RootPart
			Velocity.Velocity = RootPart.CFrame.LookVector
			Velocity.Name = "SlideVelocity"
			
			local CD1=false
			local CD2=false
			local SlideAnimation = Humanoid:LoadAnimation(script.Slide)
			SlideAnimation.Looped = true
			SlideAnimation:Play()
			Instances[Character].Animation = SlideAnimation
			Instances[Character].Velocity = Velocity
			Instances[Character].Multiplier1 = Multiplier
			Instances[Character].Multiplier2 = SlopeMultiplier
			
			SlopeMultiplier.Value = 1
			Multiplier.Value = 1
			
			local Rah = nil
			local FollowThread = task.spawn(function()
				local lastPosition = RootPart.Position
				local lastWedge = nil
				while task.wait() do
					local Params = RaycastParams.new();
					local Shapes = {Enum.PartType.Wedge}
					local Filter = {Character}
					
					Params.FilterDescendantsInstances = Filter
					Params.FilterType = Enum.RaycastFilterType.Exclude
					
					local Direction = Vector3.new(0, -(RootPart.Size.Y+3), 0)
					local Raycast = workspace:Raycast(RootPart.Position, Direction, Params)
					if Raycast and Raycast.Instance then
						local inst : Part = Raycast.Instance
						if inst.Shape == Enum.PartType.Wedge then
							local isLower = ((RootPart.Position - lastPosition).Y < 0)
							if not isLower and not CD1 then
								if lastWedge and lastWedge ~= inst then
									SlopeMultiplier.Value -= .5
								elseif not lastWedge then
									SlopeMultiplier.Value -= .5
									lastWedge = inst				
								end
							elseif isLower then
								if lastWedge and lastWedge ~= inst then
									SlopeMultiplier.Value += .7
								elseif not lastWedge then
									SlopeMultiplier.Value += .7
									lastWedge = inst
								end
								if Rah then Rah:Cancel() end
								Multiplier.Value = 1
								Rah = TweenService:Create(
									Multiplier,
									TweenInfo.new(10, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
									{Value = 0}
								)
								Rah:Play()
							end
							lastWedge = inst
						end
					end
		
					Velocity.Velocity = RootPart.CFrame.LookVector * (Speed*SlopeMultiplier.Value*Multiplier.Value)
					lastPosition = RootPart.Position
				end
			end)
			
			table.insert(SlideThreads[Character], FollowThread)
			Rah = TweenService:Create(
				Multiplier,
				TweenInfo.new(10, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
				{Value = 0}
			)
			Rah:Play()
			
		end)
		table.insert(SlideThreads[Character], MainThread)
	elseif command == "SlideStop" then
		Humanoid.CameraOffset = Vector3.new(0,0,0)
		Character:SetAttribute("Sliding", false)
		Instances[Character].Velocity:Destroy()
		Instances[Character].Multiplier1:Destroy()
		Instances[Character].Multiplier2:Destroy()
		Instances[Character].Animation:Stop()
		for i,v in SlideThreads[Character] do
			pcall(task.cancel, v)
		end
		SlideThreads[Character] = {}
	end
end)

You should never do movement things on the server. The sliding is ping reliant now. You should do the sliding on the client. Also, try using linear velocity, as body velocity is deprecated. The reason it’s not working might be because the server sees the client differently. It could also be used to lag the server if you do it on the server.

nevermind this did NOT help at all

Not sure why this happens… but when i make sliding systems i usually just use Humanoid:MoveTo() with uhhh the sliding Animation instead of using BodyMovers or similiar stuff

If you’re willing to rewrite the code and use Humanoid:MoveTo() instead, It’s really easy to understand and do! Basically it just makes the Humanoid Move to a Position

You can constantly Call Humanoid:MoveTo(MoveDirection) function with the MoveDirection set to

Root.Position + Root.CFrame.LookVector * 100

And then you just set the Humanoid WalkSpeed Property to the Desired Sliding Speed!

And if not, then i also have POTENTIAL reasons on why the Player gets Stuck sometimes,

It could be for the reasons below

  1. The BodyVelocity MaxForce is Too High
  2. There’s a Bug in your Code!!1!1! :flushed::scream: (Might be the Multiplier Values, try removing it temporarily and check if your Character still gets stuck when bumping into a Wall/Corner, if it doesn’t then well… that’s the Problem)

if u want to make it less jank, i’d suggest adding raycasting and decrease velocity over time. that’ll help make your sliding feel more polished!

-- basically pseudocode but u can implement the basic principle of adding raycasting into ur own script
-- this is just an example, i would not just abruptly stop the player from sliding in an actual project

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local playerLocal = Players.LocalPlayer
local character = playerLocal.Character or playerLocal.CharacterAdded:Wait()
local root = character:WaitForChild("HumanoidRootPart")

local canSlide = true
local connection

local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {character}

-- handle sliding
local function slide()
	canSlide = false
	local currentTime = 0
	local slide = Instance.new("BodyVelocity")
	slide.MaxForce = Vector3.new(1, 0, 1) * 30000
	slide.Velocity = root.CFrame.LookVector * 45
	slide.Parent = root

	connection = RunService.RenderStepped:Connect(function(delta)
		-- stop sliding if collision detected
		local result = workspace:Raycast(root.Position, root.CFrame.LookVector * 8, rayParams)
		if result then
			-- stop sliding
			slide:Destroy()
			connection:Disconnect()
			connection = nil
			canSlide = true
			return
		end

		-- decrease velocity over time and stop if velocity is too low
		currentTime += delta
		if currentTime >= 0.2 then
			currentTime = 0
			slide.Velocity *= 0.8
		end

		if slide.Velocity.Magnitude <= 5 then
			slide:Destroy()
			connection:Disconnect()
			connection = nil
			canSlide = true
		end
	end)
end

UserInputService.InputBegan:Connect(function(input, isTyping)
	if isTyping or not canSlide then return end

	if input.KeyCode == Enum.KeyCode.C then
		slide()
	end
end)

This is solid advice, and I suggest you move this type of stuff to the client. Their is a reason you setnetworkownerhsip and move stuff to the client to handle networking as the world is not perfect. Things the server sees and controls are COMPLETELY different in terms of speed, networking, tweening, anything really. I suggest you look into it again.

1 Like