How to reduce decay of AssemblyLinearVelocity?

Title. I’m making a sliding script right now by following a tutorial I found. While dialling it in, I found that the rate at which the player’s AssemblyLinearVelocity decays is a bit too fast for my liking. I don’t want to increase the speed the player starts at when they enter the slide, just how slowly their velocity decays/decelerates. How can I accomplish this given my script right now? I’ve searched documentation for anything that can control the player’s rate of deceleration, but nothing seems to answer my question.

Code
local RS = game:GetService("ReplicatedStorage")
local CAS = game:GetService("ContextActionService")
local UIS = game:GetService("UserInputService")
local Promise = RS.Modules.Promise

local RaycastModule = require(RS.Modules.RaycastHitboxV4)

local plr = game.Players.LocalPlayer

local playerConfig = require(plr.PlayerScripts:WaitForChild("PlayerModule"))
local ctrls = playerConfig:GetControls()
local char = script.Parent
local hrp = char:WaitForChild("HumanoidRootPart")

local slideHitboxModel = plr.Backpack.SlideHitboxes

local duringSlideRayDirection = Vector3.new(0, -0.8, 0.3)
local detectGroundRayDirection = Vector3.new(0, -2, 0)

local slideHitbox = RaycastModule.new(slideHitboxModel)
slideHitbox.DetectionMode = RaycastModule.DetectionMode.PartMode 
slideHitbox.Visualizer = true
slideHitbox.RayDirection = Vector3.new(0, -0.6, 0.3)

local params = RaycastParams.new()
params.FilterDescendantsInstances = {plr.Character}
params.FilterType = Enum.RaycastFilterType.Exclude		
params.IgnoreWater = true

slideHitbox.RaycastParams = params

local slidingAttachment = Instance.new("Attachment")
slidingAttachment.Name = "SlidingAttachment"
slidingAttachment.Parent = hrp

local alignOrientation = Instance.new("AlignOrientation")
alignOrientation.Enabled = false 
alignOrientation.RigidityEnabled = true
alignOrientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
alignOrientation.Attachment0 = slidingAttachment
alignOrientation.Parent = hrp

local animator = plr.Character.Humanoid:WaitForChild("Animator")
local slidingAnim = RS.Assets.Animations.Sliding

local slideAcc = 45 -- Flat value for sliding

function onSlideKeyPressed(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.Begin then
		doSlide()
	end
end

CAS:BindAction("SLIDE_ACTION", onSlideKeyPressed, true, Enum.KeyCode.E)

function doSlide()

	local isInSlideMode = false
	
	local onHitEv
	local floorNormal
	
	local slidingAnimTrack = animator:LoadAnimation(slidingAnim)
	local timeSinceSlideStart = 0
	local postMovementEv

	local slideDir = 0
	local rotSpeed = 200
	
	local function reset()
		if onHitEv then
			onHitEv:Disconnect()
		end
		
		if postMovementEv then
			postMovementEv:Disconnect()
		end
		
		local activeController = ctrls:GetActiveController()

		local rightHeld = UIS:IsKeyDown(Enum.KeyCode.D) and 1 or 0
		local leftHeld = UIS:IsKeyDown(Enum.KeyCode.A) and -1 or 0
		local upHeld = UIS:IsKeyDown(Enum.KeyCode.W) and -1 or 0
		local downHeld = UIS:IsKeyDown(Enum.KeyCode.S) and 1 or 0
		
		ctrls:Enable()
		activeController.moveVector = Vector3.new(rightHeld + leftHeld, 0, upHeld + downHeld)
		slidingAnimTrack:Stop()
		slideHitbox:HitStop()
		RS.Remotes.RemoveSlideHitbox:InvokeServer()
		
		hrp.AssemblyLinearVelocity = Vector3.zero
		alignOrientation.Enabled = false
		
		char.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
	onHitEv = slideHitbox.OnHit:Connect(function(part, _, raycastResult)
		slideHitbox:HitStart()
		
		floorNormal = raycastResult.Normal
		
		local slopeVec = -hrp.CFrame.RightVector:Cross(floorNormal)
		if slopeVec.y >= 0.1 then
			if isInSlideMode then
				print("Stopped slide. Slope too steep.")
				
				reset()
			end
			return
		end
		
		if not isInSlideMode then
			print("Sliding now")
			slideHitbox.RayDirection = duringSlideRayDirection
			isInSlideMode = true
			
			alignOrientation.Enabled = true
			hrp.AssemblyLinearVelocity = Vector3.zero
			
			char.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
			ctrls:Disable()
			slidingAnimTrack:Play()
			
			local forwardForce = slopeVec.Unit * hrp.AssemblyMass * slideAcc -- Final velocity 
			hrp:ApplyImpulse(forwardForce)
			
			slideHitbox.OnHitNothing:Connect(function()
				floorNormal = nil
			end)
			
			postMovementEv = game:GetService("RunService").Heartbeat:Connect(function(dt)
				local rightHeld = UIS:IsKeyDown(Enum.KeyCode.D) and 1
				local leftHeld = UIS:IsKeyDown(Enum.KeyCode.A) and -1
				
				if (slideDir == 0) or (slideDir == 1 and rightHeld == false) or (slideDir == -1 and leftHeld == false) then
					slideDir = rightHeld or leftHeld or 0
				end
				
				timeSinceSlideStart += dt
				if floorNormal then
					local linearVelo = hrp.AssemblyLinearVelocity
					linearVelo =  linearVelo - floorNormal * linearVelo:Dot(floorNormal)
					hrp.AssemblyLinearVelocity = CFrame.fromAxisAngle(floorNormal, math.rad(-rotSpeed) * slideDir * dt) * linearVelo 

					alignOrientation.CFrame = CFrame.lookAt(hrp.CFrame.Position, hrp.CFrame.Position + hrp.AssemblyLinearVelocity)
				end

				if timeSinceSlideStart >= 0.2 then
					if (hrp.AssemblyLinearVelocity * Vector3.new(1,0,1)).Magnitude < 0.1 then
						print("Stopped slide. Reached velocity zero")
						reset()
						return
					end
				end
			end)
			

		end
	end)
	RS.Remotes.AttachSlideHitbox:InvokeServer()
	slideHitbox:HitStart()
	
	game:GetService("RunService").Heartbeat:Wait()
	game:GetService("RunService").Heartbeat:Wait()
	
	if not isInSlideMode then
		if onHitEv then
			onHitEv:Disconnect()
		end
		
		slideHitbox:HitStop()
		RS.Remotes.RemoveSlideHitbox:InvokeServer()
		print("Stopped slide. Not on valid ground")
	end
end
1 Like

You can keep multiplying their AssemblyLinearVelocity. You can also use other forces, like a VectorForce.