I’m trying to create a slope sliding mechanic for a movement system I’m working on. However, there seems to be a bouncing problem while setting the MaxSlopeAngle on the humanoid. I’d like to avoid legacy body movers. I’ve got a band-aid fix, but I’m not confident in it.
Video showing the problem:
Code here:
local DecelerateRate = 500
RunService.RenderStepped:Connect(function(DeltaTime)
local DeltaScale = DeltaTime * 60
local Raycast = workspace:Raycast(RootPart.Position, RootPart.CFrame.UpVector * -6, RaycastParam)
if Raycast then
local Normal = Raycast.Normal
local Angle = math.acos(Normal.Y)
if Angle > 0 then
--// This is my fix
RootPart:ApplyImpulse(RootPart.CFrame.UpVector * -workspace.Gravity * 15)
Humanoid.MaxSlopeAngle -= DeltaTime * DecelerateRate
else
Humanoid.MaxSlopeAngle = 57
end
end
end)
Edit: I fixed the issue by using a LinearVelocity and applying a downwards force similar to workspace.Gravity.
That’s actually what my fix was, but I wasn’t sure if it was a good solution to the problem. Even with my fix sometimes it still bounces and I’m not sure if that amount of force downwards might cause physics issues later down the line.
Here’s the code I used for this project. (R6 Only):
--// Services
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
--// Variables
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")
local Attachment = Instance.new("Attachment", RootPart)
local LinearVelocity = Instance.new("LinearVelocity", RootPart)
LinearVelocity.Attachment0 = Attachment
LinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
LinearVelocity.VectorVelocity = Vector3.zero
LinearVelocity.MaxForce = 0
local HipHeight = Character["Left Leg"].Size.Y + (0.5 * RootPart.Size.Y) + Humanoid.HipHeight --// R15 Version: (0.5 * RootPart.Size.Y) + Humanoid.HipHeight
local SlideStartTime = 1 --// How long it takes for the slide to reach max velocity. (In Seconds)
local SlideEndTime = 2 --// How long it takes for the slide to stop. (In Seconds)
local SlideMaxSpeed = 50 --// Maximum slide speed
local Sliding = false
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Character}
--// Functions
function CheckGround() --// Raycasts towards the ground and allows for an margin of error in HipHeight
local Raycast = workspace:Raycast(RootPart.Position, RootPart.CFrame.UpVector * (-HipHeight * 2), RayParams)
local Length = Raycast and (Raycast.Position - RootPart.Position).Magnitude or HipHeight * 2
return Length <= HipHeight + 0.25, Raycast
end
function SlideLerp(RayInstance, Goal)
local StartTick = tick()
local TimePassed = 0
local Start = LinearVelocity.VectorVelocity --// The LinearVelocity starting velocity
local function SanityChecks(DetectSlope) --// Use this function to change sanity checks easily
local _, GroundCheck = CheckGround()
if not GroundCheck then return true end
--if math.abs(GroundCheck.Normal.X) + math.abs(GroundCheck.Normal.Z) < 0.25 and DetectSlope then print("FOUND NON SLOPE") return true end
if not UserInputService:IsKeyDown(Enum.KeyCode.C) then return true end
if math.abs(GroundCheck.Normal.X) + math.abs(GroundCheck.Normal.Z) < 0.25 then
if DetectSlope then
return true
else
return false
end
end
return false
end
while TimePassed <= SlideStartTime do --// Lerps LinearVelocity within given time span
if SanityChecks(true) then break end
TimePassed += RunService.Heartbeat:Wait()
LinearVelocity.VectorVelocity = Start:Lerp(RayInstance.CFrame.LookVector * Goal, TimePassed/SlideStartTime) + (Vector3.yAxis * -workspace.Gravity)
end
while true do
if SanityChecks(true) then break end
RunService.Heartbeat:Wait()
end
Start = LinearVelocity.VectorVelocity
TimePassed = 0
while TimePassed <= SlideEndTime do
if SanityChecks() then break end
TimePassed += RunService.Heartbeat:Wait()
LinearVelocity.VectorVelocity = Start:Lerp(Vector3.zero, TimePassed/SlideEndTime)
end
--// Resets everything to prepare for another slide
LinearVelocity.VectorVelocity = Vector3.zero
LinearVelocity.MaxForce = 0
Sliding = false
print("Slide Finished:", (tick() - StartTick))
end
--// Init
UserInputService.InputBegan:Connect(function(Input, GPE)
if GPE then return end
if Input.KeyCode == Enum.KeyCode.C then
local _, GroundCast = CheckGround()
if GroundCast and not Sliding then
print("Found Ground")
local RayInstance = GroundCast.Instance
local Normal = GroundCast.Normal
local Steepness = math.abs(Normal.X) + math.abs(Normal.Z)
if Steepness > 0.25 then
Sliding = true
LinearVelocity.MaxForce = 100000
SlideLerp(RayInstance, 50)
end
end
end
end)
im relatively new to scripting and cant figure out how you would do this can you give me an example of how you used LinearVelocity so I can better understand it and fix my own problem with sliding?
Sorry for the late reply. The solution I did isn’t the best by any means but hopefully, it helps you get a general idea of execution. (This is also R6 btw, may be different for R15)
--// Services
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
--// Variables
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")
local Attachment = Instance.new("Attachment", RootPart)
local LinearVelocity = Instance.new("LinearVelocity", RootPart)
LinearVelocity.Attachment0 = Attachment
LinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
LinearVelocity.VectorVelocity = Vector3.zero
LinearVelocity.MaxForce = 0
local HipHeight = Character["Left Leg"].Size.Y + (0.5 * RootPart.Size.Y) + Humanoid.HipHeight --// R15 Version: (0.5 * RootPart.Size.Y) + Humanoid.HipHeight
local SlideStartTime = 1 --// How long it takes for the slide to reach max velocity. (In Seconds)
local SlideEndTime = 2 --// How long it takes for the slide to stop. (In Seconds)
local SlideMaxSpeed = 50 --// Maximum slide speed
local Sliding = false
local RayParams = RaycastParams.new()
RayParams.FilterDescendantsInstances = {Character}
--// Functions
function CheckGround() --// Raycasts towards the ground and allows for an margin of error in HipHeight
local Raycast = workspace:Raycast(RootPart.Position, RootPart.CFrame.UpVector * (-HipHeight * 2), RayParams)
local Length = Raycast and (Raycast.Position - RootPart.Position).Magnitude or HipHeight * 2
return Length <= HipHeight + 0.25, Raycast
end
function SlideLerp(RayInstance, Goal)
local StartTick = tick()
local TimePassed = 0
local Start = LinearVelocity.VectorVelocity --// The LinearVelocity starting velocity
local function SanityChecks(DetectSlope) --// Use this function to change sanity checks easily
local _, GroundCheck = CheckGround()
if not GroundCheck then return true end
--if math.abs(GroundCheck.Normal.X) + math.abs(GroundCheck.Normal.Z) < 0.25 and DetectSlope then print("FOUND NON SLOPE") return true end
if not UserInputService:IsKeyDown(Enum.KeyCode.C) then return true end
if math.abs(GroundCheck.Normal.X) + math.abs(GroundCheck.Normal.Z) < 0.25 then
if DetectSlope then
return true
else
return false
end
end
return false
end
while TimePassed <= SlideStartTime do --// Lerps LinearVelocity within given time span
if SanityChecks(true) then break end
TimePassed += RunService.Heartbeat:Wait()
LinearVelocity.VectorVelocity = Start:Lerp(RayInstance.CFrame.LookVector * Goal, TimePassed/SlideStartTime) + (Vector3.yAxis * -workspace.Gravity)
end
while true do
if SanityChecks(true) then break end
RunService.Heartbeat:Wait()
end
Start = LinearVelocity.VectorVelocity
TimePassed = 0
while TimePassed <= SlideEndTime do
if SanityChecks() then break end
TimePassed += RunService.Heartbeat:Wait()
LinearVelocity.VectorVelocity = Start:Lerp(Vector3.zero, TimePassed/SlideEndTime)
end
--// Resets everything to prepare for another slide
LinearVelocity.VectorVelocity = Vector3.zero
LinearVelocity.MaxForce = 0
Sliding = false
print("Slide Finished:", (tick() - StartTick))
end
--// Init
UserInputService.InputBegan:Connect(function(Input, GPE)
if GPE then return end
if Input.KeyCode == Enum.KeyCode.C then
local _, GroundCast = CheckGround()
if GroundCast and not Sliding then
print("Found Ground")
local RayInstance = GroundCast.Instance
local Normal = GroundCast.Normal
local Steepness = math.abs(Normal.X) + math.abs(Normal.Z)
if Steepness > 0.25 then
Sliding = true
LinearVelocity.MaxForce = 100000
SlideLerp(RayInstance, 50)
end
end
end
end)