Dash momentum not stopping in time

hey there, as seen in the title, I’ve been having trouble stopping the player after a dash
upon the dash completion, it would continue moving and stop after a while
I’m not sure if it’s a LinearVelocity issue, but it’s definitely making my dash quite annoying to use

here’s my localscript code (ignore the messy code):

local contextActionService = game:GetService("ContextActionService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local runService = game:GetService("RunService")

local swiftTween = require(replicatedStorage:WaitForChild("SwiftTween"))

local gameMechanicSetup = replicatedStorage:WaitForChild("GameMechanicSetup")
local playerEvents = replicatedStorage:WaitForChild("PlayerEvents")
local dashSetup = gameMechanicSetup:WaitForChild("DashSetup")
local playerAttackEvent = playerEvents:WaitForChild("PlayerAttack")

local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid:Humanoid = character:WaitForChild("Humanoid")
local hrp = character:WaitForChild("HumanoidRootPart")

local animator:Animator = humanoid:WaitForChild("Animator")
local animation = script:WaitForChild("Animation")

--Early declaration
local frontDashAttach = nil
local linearVelo = nil

--Detection params
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.MaxParts = 1000
params.RespectCanCollide = true
params.FilterDescendantsInstances = {workspace.Baseplate, character}

--TODO: Check for hitbox on the client instead of the server, and upon enemy detection, send an event to the server
--      and skip the animation to the punch anim event

--Good arguments check
dashSetup.OnClientEvent:Connect(function(attachment, lv)
	if attachment:IsA("Attachment") and lv:IsA("LinearVelocity") then
		frontDashAttach = attachment
		linearVelo = lv
		print("Good arguments received")
	else
		warn("Bad arguments received, check for errors")
	end
end)

--Movement functions
local function removeVelocity()
	hrp.Anchored = true
	
	for i, movingPart in character:GetDescendants() do
		if not movingPart:IsA("BasePart") then continue end
		
		movingPart.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
	end
	
	hrp.Anchored = false
end

local function velocitySetup()
	linearVelo.Enabled = true
	linearVelo.Attachment0 = frontDashAttach
	linearVelo.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
	linearVelo.ForceLimitMode = Enum.ForceLimitMode.PerAxis
	linearVelo.MaxAxesForce = Vector3.new(100000, 0, 100000) --Vector3.new(math.huge, 0, math.huge)
	linearVelo.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
	linearVelo.VectorVelocity = Vector3.new(100, 0, 0)
end

local function handleAction(actionName, inputState, inputObject)
	if actionName == "Dash" then
		if inputState == Enum.UserInputState.Begin then
			--Loads track and stops all other animations
			local animTrack = animator:LoadAnimation(animation)
			local currentPlayingTracks = animator:GetPlayingAnimationTracks()
			for i, v in currentPlayingTracks do
				v:Stop()
			end
			animTrack:Play(0.1)
			
			playerAttackEvent:FireServer(hrp)
			
			--Apply stun
			humanoid.WalkSpeed = 0 --TODO: Do this on the server
			
			--LinearVelocity set up
			velocitySetup()
			print("Dashing")
			
			--Hitbox logic
			local hitboxParts = nil
			local connection = nil --For global access
			local attackDB = {} --Avoid damage repetition
			
			connection = runService.Heartbeat:Connect(function()
				local hitboxSize = Vector3.new(4.6, 5.5, 4)
				local hitboxCFrame = (hrp.CFrame - Vector3.new(0, 0.5, 0)) + (hrp.CFrame.LookVector * (hitboxSize.Z / 1.75))
				
				hitboxParts = workspace:GetPartBoundsInBox(hitboxCFrame, hitboxSize, params)
				
				for i, part in hitboxParts do
					if part.Parent:FindFirstChild("Humanoid") and animTrack.IsPlaying == true then
						
						animTrack.TimePosition = 0.66
						removeVelocity()
						connection:Disconnect()
						print("Disconnected and hit")
						return
					end
				end
				
			end)
			
			animTrack.Ended:Connect(function()
				print("Ended, nothing was hit")
				linearVelo.VectorVelocity = Vector3.new(0, 0, 0)
				connection:Disconnect()
				
				humanoid.WalkSpeed = 16
				linearVelo.Enabled = false
				animTrack:Stop()
				return
			end)
			
			--Tweening
			swiftTween.CreateTween(
				linearVelo,
				0.8,
				"Sine",
				"In",
				0,
				false,
				0,
				{VectorVelocity = Vector3.new(0, 0, 0)},
				true
			)
			
			--Anim event reached
			animTrack:GetMarkerReachedSignal("Unstun"):Connect(function()
				print("Track ended!")
				linearVelo.VectorVelocity = Vector3.new(0, 0, 0)
				
				humanoid.WalkSpeed = 16
				linearVelo.Enabled = false
				animTrack:Stop(0.5)
			end)
			
		else
			--print("Input state changed/stopped")
		end
	end
end

contextActionService:BindAction("Dash", handleAction, true, Enum.KeyCode.F)

--print("Set up!")

result:

as you can see, it’s still going after I’ve hit the enemy, and I’m looking for a surefire way of stopping the velocity in front of the enemy
if anybody has any solutions, please help me out! thanks so much :happy2:

The issue is most likely in the removeVelocity() function. You’re not disabling the linearVelo at any point, which means it keeps applying force. Also, modifying the AssemblyLinearVelocity of all character parts seems unnecessary — disabling it just on the HumanoidRootPart (hrp) should be enough.

Try this version:

local function removeVelocity()
    linearVelo.VectorVelocity = Vector3.new(0, 0, 0) -- First, disable the LinearVelocity forces
    task.wait() -- Might not be necessary, test with and without it
    hrp.AssemblyLinearVelocity = Vector3.new(0, 0, 0) -- Then reset the hrp's velocity
end

hmm, it seems to still be moving after I hit an enemy, what do u think about increasing the hitbox, or giving the player a box collision?

I don’t think increasing the hitbox will help much; it might actually look odd if you can hit from too far away. Also, giving the player a collision box might complicate things.

In my game, I made a dash that stops after a short time, and the only thing I do to make it stop instantly is this:

velocity.Enabled = false
characterController.Root.AssemblyLinearVelocity = Vector3.zero

This makes my character stop immediately.

Maybe the issue lies elsewhere. For example, I noticed that your hitbox moves forward every RunService step, and when it detects something, it stops. But if you look, the hitbox actually overshoots the enemy before detecting it. This could be why it doesn’t matter if you’ve already disabled the velocity the detector has already passed the enemy.

ohh, the hitbox overshooting the enemy part made quite a lot of sense actually, that’s why the problem happensss
if you could be so kind would you send me a tutorial about CharacterControllers? thanks!

Sorry, I need to review what I sent. CharacterController is a module that contains important parts of the character for easy access and controls the character. If you want to see how all of that works, the Roblox Platformer template helps me.

Actually, for your case, it would be something like:

linearVelo.Enabled = false
hrp.AssemblyLinearVelocity = Vector3.zero

ooh alright, thanks for the module recommendation :0
but going back to my script, I tried this already in my original script

Could I see what changed? Or maybe you could tell me if the character now stops behind the hitbox.

OH WAIT IT WORKED, I’m not sure what I did but now it works, thank you so much!!

1 Like

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