How to create a sliding script that only works on slopes

I’m trying to create a script to make the player slide down a slope.
I’ve tried searching for ways to do what I’m trying to do and so far have got. (This is inside another keybind connection function on the server)

local linearVelocity = Instance.new('LinearVelocity')
linearVelocity.Parent = root
linearVelocity.Name = 'SlideVelocity'
linearVelocity.Attachment0 = root:FindFirstChild('RootAttachment')
linearVelocity.MaxForce = 1000000
linearVelocity.VectorVelocity = Vector3.new(0,0,0)
linearVelocity.Visible = true
		
player:SetAttribute("isSliding", true)

RunService.Heartbeat:Connect(function(dt)
	if player:GetAttribute("isSliding") == true then
		hum.PlatformStand = true
				
		local rayParams = RaycastParams.new()
		rayParams.FilterDescendantsInstances = {character}
		rayParams.FilterType = Enum.RaycastFilterType.Exclude
		
		local ray = workspace:Raycast(part.Position, Vector3.new(0,-1000,0), rayParams)
		local upVector = Vector3.yAxis
		if ray then
			upVector = ray.Normal
		end
		local rightVector = downVector:Cross(upVector)

		part.CFrame = CFrame.fromMatrix(root.Position+Vector3.yAxis*5,rightVector,upVector)
				
		local vector = Vector3.new(CFrame.fromMatrix(root.Position+Vector3.yAxis*5,rightVector,upVector):ToOrientation())
		local newVector = Vector3.new(math.deg(vector.X), math.deg(vector.Y), math.deg(vector.Z))

		linearVelocity.VectorVelocity = Vector3.new(
			newVector.X,
			-newVector.Y,
			newVector.Z
		)
	end
end)

So far, the code is moving the character, however the character is being moved in incorrect directions. I’m assuming that is is due to the :ToOrientation but I don’t know how to fix it.

I’m open to any suggestions, including changing the linear velocity to another method, I just need some way to make this work lol.

Thanks

2 Likes

How about using a ragdoll system? Ragdolls will slide down slopes based on gravity.

Do what @Sir_Highness said, or just make the player sit.

Here is a script I made a while back, the problem is solved by changing gravity really high:

local debounce = false
local UserInputService = game:GetService("UserInputService")

local function onKeyPress(input)
	if input == "q" then
		if debounce == false then
			debounce = true
			local humanoidRootPart = game.Players.LocalPlayer.Character.HumanoidRootPart
			local humanoid = game.Players.LocalPlayer.Character.Humanoid
			local anim = Instance.new("Animation")
			anim.AnimationId = "rbxassetid://18237726269"

			--Animate

			local playerAnims = humanoid.Animator:GetPlayingAnimationTracks() -- gets all Animations

			for _,animation in playerAnims do -- Iterates through all Animations
				print(animation)
				animation:Stop() -- stops animations
			end

			game.Players.LocalPlayer.Character["Animate"].Enabled = false



			local animationTrack = humanoid:LoadAnimation(anim)

			wait(0.01)
			
			workspace.Gravity = 90000

			animationTrack:Play()

			local DashParticle = Instance.new("ParticleEmitter")
			DashParticle.Texture = "rbxassetid://14197943648"
			DashParticle.Parent = game.Players.LocalPlayer.Character:FindFirstChild("HumanoidRootPart")
			DashParticle.EmissionDirection = "Back"
			DashParticle.Lifetime = NumberRange.new(0.5,1)
			DashParticle.Rate = 90
			DashParticle.Orientation = Enum.ParticleOrientation.VelocityParallel
			DashParticle.Speed = NumberRange.new(3)
			DashParticle.Squash = NumberSequence.new(-1.5)

			for i = 0,10,1 do -- move the player forward
				task.wait(0.00001)
				local currentCFrame = humanoidRootPart:GetPivot()
				local forwardVector = currentCFrame.LookVector * 2
				local targetCFrame = currentCFrame + forwardVector
				humanoidRootPart:PivotTo(targetCFrame)
			end

			DashParticle.Enabled = false

			wait(0.5)
			workspace.Gravity = 196.2
			game.Players.LocalPlayer.Character["Animate"].Enabled = true
			wait(0.01)

			--Re-Enable Movement (Kind of hacky)
			game.Players.LocalPlayer.Character:FindFirstChild("Humanoid").Jump = true
			task.wait(0.00001)
			humanoidRootPart.Velocity = Vector3.new(0,0,0)
			wait(1) -- 1 second cool down
			debounce = false

		end

	end


end
game.Players.LocalPlayer:GetMouse().KeyDown:Connect(onKeyPress) -- on key press

-- Script for adding a button to the screen
local function MobileGUI()	
	-- Create a ScreenGui
	local screenGui = Instance.new("ScreenGui")
	screenGui.Parent = game.Players.LocalPlayer:WaitForChild("PlayerGui")

	local button = Instance.new("ImageButton")
	local corner = Instance.new("UICorner")
	button.Size = UDim2.new(0, 50, 0, 50)
	button.Position = UDim2.new(1, -180,1, -80)
	button.Image = "http://www.roblox.com/asset/?id=15427166971"
	button.Parent = screenGui
	button.BackgroundColor3 = Color3.new(1, 1, 1)
	corner.Parent = button
	corner.CornerRadius = UDim.new(0.5, 0)


	-- Connect a function to the button's 'Activated' event
	button.Activated:Connect(function()
		onKeyPress("q")
	end)
end

local function detectMobile(plyr)
	local isMobile = UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled
	if isMobile then
		MobileGUI()
	end
end

detectMobile(game.Players.LocalPlayer)

What is the value of downVector when it’s crossed with upVector?

You won’t get the correct rightVector if you don’t have the correct downVector, which I assume is parallel to the slope and heading downwards. I don’t see any calculations involving it before you do the cross product.

Oopsies, I forgot to close this, I found out that my problem was simply that I was meant to use CFrame.LookVector instead of CFrame:ToOrientation. And then edit a few other things from there. Thanks to anyone who did respond though :slight_smile:

If anyone wants the code, I’ll paste it here (you may have to remove the initial velocity stuff that is currently broken it’s WIP, obviously there is other variables you will have to redefine aswell though lol, its not gonna work out of the box):

---------------
-- FUNCTIONS --
---------------

local function CreateLinearVelocity(root:BasePart)
	local newVelocity = Instance.new('LinearVelocity')
	newVelocity.Parent = root
	newVelocity.Name = 'SlideVelocity'
	newVelocity.Attachment0 = root:FindFirstChild('RootAttachment')
	newVelocity.MaxForce = 1000000
	newVelocity.VectorVelocity = Vector3.new(0,0,0)
	newVelocity.Visible = true
	newVelocity.Enabled = false
	
	return newVelocity
end

local function ResetAttributes(player:Player)
	player:SetAttribute("isSliding", false)
	player:SetAttribute('slidingTime', 0)
end

---------------------
-- EVENT FUNCTIONS --
---------------------

slideEvent.OnServerEvent:Connect(function(player, ending, character:Model) --when player clicks the slide button
	local root = character:FindFirstChild('HumanoidRootPart')
	local hum = character:FindFirstChild('Humanoid')
	
	if player:GetAttribute("isSliding") == nil then
		player:SetAttribute("isSliding", false)
	end
	
	if ending then
		root:FindFirstChild('SlideVelocity'):Destroy()
		
		ResetAttributes(player)
		player:SetAttribute("isAttemptingToSlide", false)
	else
		local linearVelocity = CreateLinearVelocity(root)
		
		player:SetAttribute("isSliding", true)
		player:SetAttribute('slidingTime', 0)
		player:SetAttribute("isAttemptingToSlide", true)

		RunService.Heartbeat:Connect(function(dt)
			if player:GetAttribute("isAttemptingToSlide") then
				local initialVelocity = Vector3.new(0,0,0)
				if not player:GetAttribute('isSliding') then
					initialVelocity = root.AssemblyLinearVelocity
				end
				
				local playerSlideTime = player:GetAttribute('slidingTime')
				player:SetAttribute('slidingTime', playerSlideTime + dt)
				
				local rayParams = RaycastParams.new()
				rayParams.FilterDescendantsInstances = {character}
				rayParams.FilterType = Enum.RaycastFilterType.Exclude
				
				local ray = workspace:Raycast(root.Position, Vector3.new(0,-10,0), rayParams)
				local upVector = Vector3.yAxis
				
				if ray then
					upVector = ray.Normal
				end
				
				local rightVector = downVector:Cross(upVector)
				
				local useCframe = CFrame.fromMatrix(root.Position, rightVector, upVector)
				
				local multiplierMultiplier = player:GetAttribute('slidingTime')
				local vector = Vector3.new(0,0,0)
				local initialVector = Vector3.new(initialVelocity.Magnitude, 0, initialVelocity.Magnitude)
				
				if multiplierMultiplier >= 1 then
					vector = (useCframe.LookVector * (20 * (multiplierMultiplier))) + initialVector
				else
					vector = (useCframe.LookVector * 20) + initialVector
				end

				linearVelocity.VectorVelocity = vector
				
				if linearVelocity.VectorVelocity.Magnitude > 0 then
					linearVelocity.Enabled = true
				else
					ResetAttributes(player)
				end
			end
		end)
	end
end)

Edit from a few days after this post: In the end I completely rewrote the code and instead just used an AlignOrientation instance and Humanoid.PlatformStand to essentially just let the character slide down the hill based on roblox physics. To fix bouncing or that I edited the HumanoidRootPart.CustomPhysicalProperties. This approach was SO MUCH MORE SIMPLE and worked almost exactly the same, so yk, thats cool.

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