Need help with BodyVelocity in my dashing script

Hello, I’m trying to make a dashing script with BodyVelocity and want the dashing to last until the player stops holding a certain key on their keyboard.
The issue is I am trying to figure out how to make the dashing end at a given time while the player is holding a key.
I tried doing a while true do loop and whenever i press E it just keeps moving me with no end or stopping to it
heres the script:

	if input.KeyCode == Enum.KeyCode.E then
		KeyPressed = true
		print("player is pressing E")
		while true do
			wait()
			player.Character.HumanoidRootPart.Velocity = player.Character.HumanoidRootPart.CFrame.lookVector * 50
		end
		
	end
			UIS.InputEnded:Connect(function(input)
				if input.KeyCode == Enum.KeyCode.E then
				KeyPressed = false
				if print("E key isnt being held")then
					player.Character.HumanoidRootPart.Velocity = player.Character.HumanoidRootPart.CFrame.lookVector * 0
				end

instead of while true do.

do this instead

while KeyPressed do

1 Like

One trick with InputObjects is that once you’ve got a reference to that object, you can set up a connection that responds to changes in just that InputObject.

When UserInputService.InputBegan fires, it passes along an InputObject representing e.g. the action of pushing the E key. That InputObject has a Changed event, which we can listen to and which fires when te E key is released again. That lets us set it all up in a single “connection” to InputBegan.

Example dash script using UserInputService
--Put in StarterPlayer.StarterCharacterScripts
local InputS = game:GetService("UserInputService")
local RunS = game:GetService("RunService")

local camera = game.Workspace.CurrentCamera

local c = script.Parent
local humanoid = c:WaitForChild("Humanoid")
local rootPart = c:WaitForChild("HumanoidRootPart")

local dashBodyVelocity = Instance.new("BodyVelocity")
dashBodyVelocity.Name = "DashBodyVelocity"
dashBodyVelocity.MaxForce = Vector3.new()
dashBodyVelocity.Velocity = Vector3.new()
dashBodyVelocity.Parent = rootPart

local dashSpeed = 50
local dashForce = 40000

InputS.InputBegan:Connect(function(inputObject)
	if inputObject.KeyCode == Enum.KeyCode.Q or inputObject.KeyCode == Enum.KeyCode.E then
		local dashDirection = inputObject.KeyCode == Enum.KeyCode.Q and -1 or 1
		
		--Start dashing
		dashBodyVelocity.Velocity = camera.CFrame.RightVector * dashSpeed * dashDirection
		dashBodyVelocity.MaxForce = Vector3.new(1, 0, 1) * dashForce
		
		local changedC --must be declared before assignment because otherwise it won't be visible to the connected funciton.
		changedC = inputObject:GetPropertyChangedSignal("UserInputState"):Connect(function()
			if inputObject.UserInputState == Enum.UserInputState.End then
				changedC:Disconnect() --clean up the connection, otherwise it'd exist forever
				
				--Stop dashing
				dashBodyVelocity.Velocity = Vector3.new()
				dashBodyVelocity.MaxForce = Vector3.new()
			end
		end)
	end
end)

You can use ContextActionService to do all of this in a slightly shorter way, and I think it’s easier to understand too:

Example dash script with ContextActionService
local ActionS = game:GetService("ContextActionService")
local RunS = game:GetService("RunService")

local camera = game.Workspace.CurrentCamera

local c = script.Parent
local humanoid = c:WaitForChild("Humanoid")
local rootPart = c:WaitForChild("HumanoidRootPart")

local dashBodyVelocity = Instance.new("BodyVelocity")
dashBodyVelocity.Name = "DashBodyVelocity"
dashBodyVelocity.MaxForce = Vector3.new()
dashBodyVelocity.Velocity = Vector3.new()
dashBodyVelocity.Parent = rootPart

local dashSpeed = 50
local dashForce = 40000

function onDashInputChanged(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.Begin then
		local dashDirection = inputObject.KeyCode == Enum.KeyCode.Q and -1 or 1
		
		--Start dashing
		dashBodyVelocity.Velocity = camera.CFrame.RightVector * dashSpeed * dashDirection
		dashBodyVelocity.MaxForce = Vector3.new(1, 0, 1) * dashForce
	else --inputState = End
		--Stop dashing
		dashBodyVelocity.Velocity = Vector3.new()
		dashBodyVelocity.MaxForce = Vector3.new()
	end
end

ActionS:BindAction("dashRight", onDashInputChanged, false, Enum.KeyCode.Q, Enum.KeyCode.E)

CAS is great because you can easily overwrite the binding to do nothing when you’re in a different context, e.g. if the player opens a menu where you don’t want them to accidentally dash when pressing E.

2 Likes

So I can use your dash script example using UserInputService, and it will allow the player to move in the direction the player wants to move with lookVector? When I tried your script, it moved me to the side like side stepping,although i appreciate your effort in this, but that wasn’t what i wanted. The original script i had was to make the player dash while holding down E and whatever direction they want. Then again it my fault for not mentioning this.The problem I had was whenever hold down the E key it doesn’t let me stop moving my character, once I am done pressed down the E key.

edit: also how come theres a -1 or 1 in line 21 of the code for the example of the UserInputService?

This is a “trick” that uses the fact that if you multiply a direction represented by a vector by -1, you get a vector in the opposite direction. So instead of having an if-else statement where both execution paths are the same code repeated except for a * 1 or *-1, I just change the direction that the force is applied by multiplying it by either 1 (doing nothing) or -1 (flipping the direction).

Instead of having an if-else statement to set dashDirection, I use something like a “ternary” operator common in other programming languages. Lua doesn’t have that operator, but the same can be accomplished with the and and or logical operators. The effect is that if the Q key was pressed dashDirection is set to -1, otherwise it’s set to 1. If you want to know more about it, search for “Lua ternary”.

Sure, something like this should do the trick:

Code
--Put in StarterPlayer.StarterCharacterScripts
local InputS = game:GetService("UserInputService")
local RunS = game:GetService("RunService")

local camera = game.Workspace.CurrentCamera

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")

local dashBodyVelocity = Instance.new("BodyVelocity")
dashBodyVelocity.Name = "DashBodyVelocity"
dashBodyVelocity.MaxForce = Vector3.new()
dashBodyVelocity.Velocity = Vector3.new()
dashBodyVelocity.Parent = rootPart

local dashSpeed = 50
local dashForce = 40000

InputS.InputBegan:Connect(function(inputObject)
	if inputObject.KeyCode == Enum.KeyCode.E then
		--Start dashing
		dashBodyVelocity.Velocity = camera.CFrame.LookVector * dashSpeed
		dashBodyVelocity.MaxForce = Vector3.new(1, 0, 1) * dashForce
		
		local changedC, renderSteppedC --must be declared before assignment because otherwise it won't be visible to the connected funciton.

		--Stop dashing when dash key is released
		changedC = inputObject:GetPropertyChangedSignal("UserInputState"):Connect(function()
			if inputObject.UserInputState == Enum.UserInputState.End then
				changedC:Disconnect() --clean up the connection, otherwise it'd exist forever
				renderSteppedC:Disconnect() --stop updating the direction by disconnecting 
				
				--Stop dashing
				dashBodyVelocity.Velocity = Vector3.new()
				dashBodyVelocity.MaxForce = Vector3.new()
			end
		end)

		--Update dash force direction every frame, otherwise player would just dash in one direction forever
		renderSteppedC = RunService.RenderStepped:Connect(function()
			dashBodyVelocity.Velocity = camera.CFrame.LookVector * dashSpeed
		end)
	end
end)
3 Likes

Thank you for going into detail with this i appreciate it.This has solved my problem.

1 Like