Dash system fix

Hey! I see you’re having some trouble with your dash script. There are a few issues with the implementation you chose and I’d love to help you with them! I rewrote your script to include the features you requested as well as some general optimizations:

Code
-- Written by AverageLua

local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Character = script.Parent
if not Character then
	warn("Could not find character, please place dash script in StarterCharacterScripts!")
	return
end

local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Animator = Character:WaitForChild("Humanoid"):WaitForChild("Animator")

local DashVelocityMagnitude = 45 -- dash speed
local DashCooldown = 3 -- cooldown for dashing
local DashSoundId = "rbxassetid://0" -- insert dash sound id

local CurrentlyDashing = false
local LastDashClock = 0

local ButtonPressTimings = {
	W = 0,
	A = 0,
	S = 0,
	D = 0
}

local ButtonDirectionMap = {
	W = Vector3.new(0, 0, -1),
	A = Vector3.new(-1, 0, 0),
	S = Vector3.new(0, 0, 1),
	D = Vector3.new(1, 0, 0)
}

local ButtonAnimationMap = {
	W = "rbxassetid://0",
	A = "rbxassetid://0",
	S = "rbxassetid://0",
	D = "rbxassetid://0",
}

local VelocityAttachment = Instance.new("Attachment", HumanoidRootPart)
local DashLinearVelocity = Instance.new("LinearVelocity")
DashLinearVelocity.Enabled = false
DashLinearVelocity.MaxForce = 1e5
DashLinearVelocity.Attachment0 = VelocityAttachment
DashLinearVelocity.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
DashLinearVelocity.Parent = HumanoidRootPart

for Button, AnimationId in ButtonAnimationMap do
	local TemporaryAnimation = Instance.new("Animation")
	TemporaryAnimation.AnimationId = AnimationId
	ButtonAnimationMap[Button] = Animator:LoadAnimation(TemporaryAnimation)
	TemporaryAnimation:Destroy()
end

local function PlayDashSound()
	local NewDashSound = Instance.new("Sound")
	NewDashSound.SoundId = DashSoundId

	if not NewDashSound.IsLoaded then
		NewDashSound.Loaded:Wait()
	end
	NewDashSound.Parent = HumanoidRootPart

	NewDashSound.Ended:Once(function()
		NewDashSound:Destroy()
	end)
	NewDashSound:Play()
end

local function Dash(DirectionKey)
	if CurrentlyDashing or os.clock() - LastDashClock < DashCooldown then
		return
	end
	CurrentlyDashing = true

	if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then
		-- Players who are not mouse locked can only dash forward.
		DirectionKey = "W"
	end

	local DashDirection = ButtonDirectionMap[DirectionKey]
	local DashAnimationTrack = ButtonAnimationMap[DirectionKey]
	DashAnimationTrack:Play()

	PlayDashSound()

	DashLinearVelocity.VectorVelocity = DashDirection * DashVelocityMagnitude
	DashLinearVelocity.Enabled = true

	task.delay(DashAnimationTrack.Length, function()
		DashLinearVelocity.Enabled = false
		DashLinearVelocity.VectorVelocity = Vector3.zero

		CurrentlyDashing = false
		LastDashClock = os.clock()
	end)
end

local function HandleAction(ActionName, InputState, InputObject)
	if InputState == Enum.UserInputState.Begin then
		local ButtonPressDelta = os.clock() - ButtonPressTimings[ActionName]
		ButtonPressTimings[ActionName] = os.clock()

		if ButtonPressDelta < .15 then
			Dash(ActionName)
		end
	end
	return Enum.ContextActionResult.Pass
end

ContextActionService:BindAction("W", HandleAction, false, Enum.KeyCode.W)
ContextActionService:BindAction("A", HandleAction, false, Enum.KeyCode.A)
ContextActionService:BindAction("S", HandleAction, false, Enum.KeyCode.S)
ContextActionService:BindAction("D", HandleAction, false, Enum.KeyCode.D)

(Place this code in a LocalScript within StarterCharacterScripts. Modify the variables at the top of the script to customize dash speed, dash cooldown, and the sound played when dashing. Also be sure to set AnimationIds within the ButtonAnimationMap table.)

There are a number of details I changed in the updated version. For starters, I opted to use ContextActionService instead of UserInputService for key press registration as it’s considered better practice. I also changed some logic for the Dash function code to make it simpler and easier to read. I added the dash sound and dash cooldown functionality you mentioned in your original post as well. Players who are not mouse locked can only dash forwards, you can remove this functionality by commenting out the if statement on line 80.

Note: I didn’t include the code that does the VFX when dashing to make the script usuable for more people. If you’d like to include this functionality, add this code on line 84:

Code
-- Written by AverageLua

task.delay(1.5, function()
	local DashEffect = ReplicatedStorage.DustTrail:Clone()
	DashEffect.Parent = workspace

	if DirectionKey == "A" then
		DashEffect.DustRight:Destroy()
		DashEffect.CFrame = Character["Right Leg"].CFrame * CFrame.new(-1, 0, -2)
	elseif DirectionKey == "D" then
		DashEffect.DustLeft:Destroy()
		DashEffect.CFrame = Character["Left Leg"].CFrame * CFrame.new(3, 2, 5)
	else
		DashEffect.DustLeft:Destroy()

		if DirectionKey == "W" then
			DashEffect.CFrame = Character:GetPivot() * CFrame.new(0, -1, 3)
		else
			DashEffect.CFrame = Character:GetPivot() * CFrame.new(0, -1, -.5)
		end
	end

	for _, Object in DashEffect:GetDescendants() do
		if Object:IsA("ParticleEmitter") then
			Object:Emit(5)
		end
	end

	task.delay(.5, DashEffect.Destroy, DashEffect)
end)