Double Midair Dash Issue

Hello! So recently, I’ve been trying to make sure a midair dash can only be done once in the air. This does work. However, if the player double jumps after dashing, the double jump enables them to be able to dash again. I don’t want this. If they double jump, it should keep them from dashing again until they touch the ground. Also, despite the massive amount of code, I am not even close to an expert at coding.
Here’s the Dash Code

-- Dash Ability
local UIS = game:GetService("UserInputService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local char = script.Parent

local dashAnim = Instance.new("Animation")
dashAnim.AnimationId = "rbxassetid://16893547895"
local keybind = Enum.KeyCode.E

local canDash = true  -- Flag to check if the player can dash
local isDashing = false
local hasDoubleJumped = false  -- Flag to check if the player has double jumped
local dashCooldown = 0.5  -- Cooldown period in seconds
local lastDashTime = 0  -- Time of the last dash

humanoid.StateChanged:Connect(function(old, new)
	if new == Enum.HumanoidStateType.Freefall then
		wait(0.1)
		canDash = true
	elseif new == Enum.HumanoidStateType.Flying or new == Enum.HumanoidStateType.Jumping or new == Enum.HumanoidStateType.Running or new == Enum.HumanoidStateType.RunningNoPhysics or new == Enum.HumanoidStateType.Landed or new == Enum.HumanoidStateType.PlatformStanding then
		canDash = false
		isDashing = false
		hasDoubleJumped = false
	end
end)

UIS.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed or not canDash or isDashing then
		return
	end

	local currentTime = tick()
	if input.KeyCode == keybind and currentTime - lastDashTime >= dashCooldown then
		if not hasDoubleJumped then
			isDashing = true
			canDash = false
			lastDashTime = currentTime  -- Update last dash time
			
			local playAnim = char.Humanoid:LoadAnimation(dashAnim)
			playAnim:Play()

			local sound = Instance.new("Sound")
			sound.SoundId = "rbxassetid://9113069681"
			sound.Parent = humanoid.Parent
			sound.Volume = 0.5
			sound:Play()

			local forwardDash = char.HumanoidRootPart:FindFirstChildOfClass("BodyVelocity")
			if forwardDash then
				forwardDash:Destroy()
			end

			local dash = Instance.new("BodyVelocity")
			dash.MaxForce = Vector3.new(1,1,1) * 18000
			dash.Velocity = char.HumanoidRootPart.CFrame.lookVector * 160
			char.HumanoidRootPart.Velocity = Vector3.new()
			dash.Parent = char.HumanoidRootPart

			for count = 1, 8 do 
				wait(0.08) --changing number shortens or lengthens dash and its animation
				dash.Velocity = dash.Velocity * 0.825
			end
			playAnim:Stop()
			dash:Destroy()
			isDashing = false
				end
			end
		end)
UIS.JumpRequest:Connect(function()
		isDashing = false
		char.HumanoidRootPart:FindFirstChildOfClass("BodyVelocity"):Destroy()
end)

Here’s the Double Jump Code

-- Double Jump
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")

local localPlayer = Players.LocalPlayer
local character
local humanoid

local canDoubleJump = false
local hasDoubleJumped = false
local hasDashed = false
local oldPower
local TIME_BETWEEN_JUMPS = 0.2
local DOUBLE_JUMP_POWER_MULTIPLIER = 1.3
local lastJumpTime = 0
local DOUBLE_JUMP_ANIMATION = "rbxassetid://17310815039"
function playAnimation(animationId)
	if humanoid and humanoid:IsDescendantOf(character) then
		local animation = Instance.new("Animation")
		animation.AnimationId = animationId
		animationId = DOUBLE_JUMP_ANIMATION
		local animTrack = humanoid:LoadAnimation(animation)
		local sound = Instance.new("Sound")
		sound.SoundId = "rbxassetid://271111328"
		sound.Parent = humanoid.Parent
		sound.Volume = 0.5
		sound:Play()
		animTrack:Play()
		wait(0.5)
		animTrack:Stop()
	end
	end
function onJumpRequest()
	if not character or not humanoid or not character:IsDescendantOf(workspace) or
		humanoid:GetState() == Enum.HumanoidStateType.Dead then
		return
	end

	local currentTime = tick()
	if currentTime - lastJumpTime < TIME_BETWEEN_JUMPS then
		return  -- Prevent rapid double jumps
	end

	lastJumpTime = currentTime

	if humanoid:GetState() == Enum.HumanoidStateType.Freefall and canDoubleJump and not hasDoubleJumped then
		hasDoubleJumped = true
		humanoid.JumpPower = oldPower * DOUBLE_JUMP_POWER_MULTIPLIER
		humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		playAnimation(DOUBLE_JUMP_ANIMATION)
	end
end

local function characterAdded(newCharacter)
	character = newCharacter
	humanoid = newCharacter:WaitForChild("Humanoid")
	hasDoubleJumped = false
	canDoubleJump = false
	oldPower = humanoid.JumpPower
	humanoid.StateChanged:Connect(function(old, new)
		if new == Enum.HumanoidStateType.Landed then
			canDoubleJump = false
			hasDoubleJumped = false
			humanoid.JumpPower = oldPower
		elseif new == Enum.HumanoidStateType.Freefall then
			wait(TIME_BETWEEN_JUMPS)
			canDoubleJump = true
			if new == Enum.HumanoidStateType.Flying then
				wait(TIME_BETWEEN_JUMPS)
				canDoubleJump = true					
			end
		end
	end)
end

Can anyone help me? I’ve been struggling for quite a while.

Are these two different scripts or are they in the same script?

In the same script for sure. Called movement script.

Try this code:

while hasDoubleJumped == true and wait() do
   if Humanoid.FloorMaterial ~= Enum.Material.Air then
       canDash = false
   end
end

Where should this be put? Into the Double Jump or Dash sections?

Try at the very end of you Double Jump section.

Nope, still allows me to dash twice. Maybe try a different placement?

Just curious, is canDash considered when dashing? I can’t see it disabling you from jumping mid-air again. And if you do, please send me the code when it occurs, it would help me a ton.

No, it’s taken in consideration when the player is in the air, but hasn’t dashed yet. IsDashing should be what you’re looking for. However, my lackluster coding could have it essentially useless. Also yeah, Candash does not disable the player from double jumping. I hope this response helps since I gotta get to bed soon.

What disables the player from double jumping then? Just replace the canDash in my previous code to that variable, and tell me if it’s still bugged.

Currently, I don’t think there is code to stop the player from double jumping. Only a cap of 1 on it. Also, it’s still bugged.

Maybe that’s why. Add into your code that if canDash ~= true then return end when the player tries to double jump. Hopefully that would help.

I’ll try it and see if the code is still bugged.

Added it at the bottom of the double jump section where your code was, but deleted your code, is this alright?

Oh wait, keep the other code. Put this if canDash ~= true then return end statment where you do the UIS.InputBegan function.

Still Bugged. Sadly, I have to go to bed and will continue tomorrow, so I won’t respond for another 19 hours or so. Before I temporarily go, here’s the updated code for both the dash and double jump:

– Double Jump
local UserInputService = game:GetService(“UserInputService”)
local Players = game:GetService(“Players”)

local localPlayer = Players.LocalPlayer
local character
local humanoid

local canDoubleJump = false
local hasDoubleJumped = false
local hasDashed = false
local oldPower
local TIME_BETWEEN_JUMPS = 0.2
local DOUBLE_JUMP_POWER_MULTIPLIER = 1.3
local lastJumpTime = 0
local DOUBLE_JUMP_ANIMATION = “rbxassetid://17310815039”
function playAnimation(animationId)
if humanoid and humanoid:IsDescendantOf(character) then
local animation = Instance.new(“Animation”)
animation.AnimationId = animationId
animationId = DOUBLE_JUMP_ANIMATION
local animTrack = humanoid:LoadAnimation(animation)
local sound = Instance.new(“Sound”)
sound.SoundId = “rbxassetid://271111328”
sound.Parent = humanoid.Parent
sound.Volume = 0.5
sound:Play()
animTrack:Play()
wait(0.5)
animTrack:Stop()
end
end
function onJumpRequest()
if not character or not humanoid or not character:IsDescendantOf(workspace) or
humanoid:GetState() == Enum.HumanoidStateType.Dead then
return
end

local currentTime = tick()
if currentTime - lastJumpTime < TIME_BETWEEN_JUMPS then
	return  -- Prevent rapid double jumps
end

lastJumpTime = currentTime

if humanoid:GetState() == Enum.HumanoidStateType.Freefall and canDoubleJump and not hasDoubleJumped then
	hasDoubleJumped = true
	humanoid.JumpPower = oldPower * DOUBLE_JUMP_POWER_MULTIPLIER
	humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
	playAnimation(DOUBLE_JUMP_ANIMATION)
end

end

local function characterAdded(newCharacter)
character = newCharacter
humanoid = newCharacter:WaitForChild(“Humanoid”)
hasDoubleJumped = false
canDoubleJump = false
oldPower = humanoid.JumpPower
humanoid.StateChanged:Connect(function(old, new)
if new == Enum.HumanoidStateType.Landed then
canDoubleJump = false
hasDoubleJumped = false
humanoid.JumpPower = oldPower
elseif new == Enum.HumanoidStateType.Freefall then
wait(TIME_BETWEEN_JUMPS)
canDoubleJump = true
if new == Enum.HumanoidStateType.Flying then
wait(TIME_BETWEEN_JUMPS)
canDoubleJump = true
while hasDoubleJumped == true and wait() do
repeat isDashing = false until humanoid.FloorMaterial ~= Enum.Material.Air
end
end
end
end)
end
– Dash Ability
local UIS = game:GetService(“UserInputService”)
local Players = game:GetService(“Players”)
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild(“Humanoid”)
local char = script.Parent

local dashAnim = Instance.new(“Animation”)
dashAnim.AnimationId = “rbxassetid://16893547895”
local keybind = Enum.KeyCode.E

local canDash = true – Flag to check if the player can dash
local isDashing = false
local hasDoubleJumped = false – Flag to check if the player has double jumped
local dashCooldown = 0.5 – Cooldown period in seconds
local lastDashTime = 0 – Time of the last dash

humanoid.StateChanged:Connect(function(old, new)
if new == Enum.HumanoidStateType.Freefall then
wait(0.1)
canDash = true
elseif new == Enum.HumanoidStateType.Flying or new == Enum.HumanoidStateType.Jumping or new == Enum.HumanoidStateType.Running or new == Enum.HumanoidStateType.RunningNoPhysics or new == Enum.HumanoidStateType.Landed or new == Enum.HumanoidStateType.PlatformStanding then
canDash = false
isDashing = false
hasDoubleJumped = false
end
end)

UIS.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed or not canDash or isDashing then
return
end
if canDash ~= true then return end
local currentTime = tick()
if input.KeyCode == keybind and currentTime - lastDashTime >= dashCooldown then
if not hasDoubleJumped then
isDashing = true
canDash = false
lastDashTime = currentTime – Update last dash time

		local playAnim = char.Humanoid:LoadAnimation(dashAnim)
		playAnim:Play()

		local sound = Instance.new("Sound")
		sound.SoundId = "rbxassetid://9113069681"
		sound.Parent = humanoid.Parent
		sound.Volume = 0.5
		sound:Play()
		

		local forwardDash = char.HumanoidRootPart:FindFirstChildOfClass("BodyVelocity")
		if forwardDash then
			forwardDash:Destroy()
		end

		local dash = Instance.new("BodyVelocity")
		dash.MaxForce = Vector3.new(1,1,1) * 18000
		dash.Velocity = char.HumanoidRootPart.CFrame.lookVector * 160
		char.HumanoidRootPart.Velocity = Vector3.new()
		dash.Parent = char.HumanoidRootPart

		for count = 1, 8 do 
			wait(0.08) --changing number shortens or lengthens dash and its animation
			dash.Velocity = dash.Velocity * 0.825
		end
		playAnim:Stop()
		dash:Destroy()
		isDashing = false
			end
		end
	end)

UIS.JumpRequest:Connect(function()
isDashing = false
char.HumanoidRootPart:FindFirstChildOfClass(“BodyVelocity”):Destroy()
end)

firstly BodyVelocity, BasePart.Velocity and the humanoid’s animation functions are deprecated and aren’t supported anymore, replace bodyvelocity with LinearVelocity, BasePart.Velocity with BasePart.AssemblyLinearVelocity and all the deprecated animation functions are present on the humanoid’s Animator class

secondly i can’t really read this code since the formatting’s all broken but consider placing breakpoints and stuff to narrow down the issue, they allow you to see what the code’s up to at the line where it was hit, here’s an example:
image