Problem trying to make a dashing system relative to the player's camera and movement

Hello! I am trying to make a dashing system for my game, but I am not very knowledgeable when it comes to things like Vector3s (and math, but a lot of people aren’t either).


(Added a red trail to help see the dashes happening better)

As you can see from the video, you can dash fine when the camera is facing one direction, but once you start moving the camera around, it looks all wrong.

The code below isn’t the full script, just cut up for better readability:

--// dash function
function dashAbility(x, z)
	local vector = Vector3.new(x, 0, z) --nil

	local dash = Instance.new("BodyVelocity")
	dash.MaxForce = Vector3.new(1e9, 1e9, 1e9)
	dash.Velocity = vector * 60
	dash.Parent = char.HumanoidRootPart

	wait(.25)
	dash:Destroy()
	wait(2.5)
	canDash = true
end

--// finds the movement direction of the player and creates the Vector3 based on the camera
local movementDirection = camera.CFrame:vectorToObjectSpace(human.MoveDirection).Unit
if math.abs(movementDirection.X) > math.abs(movementDirection.Z) then
	if movementDirection.X < 0 then
		dashAbility(movementDirection.X, 0)
	elseif movementDirection.X > 0 then
		dashAbility(movementDirection.X, 0)
	end
elseif math.abs(movementDirection.X) < math.abs(movementDirection.Z) then
	if movementDirection.Z < 0 then
		dashAbility(0, movementDirection.Z)
	elseif movementDirection.Z > 0 then
		dashAbility(0, movementDirection.Z)
	end
else end

I believe it’s because the X and Z values are supposed to be flipped when the camera is facing different directions or something. The script seems to be working fine, the problem is that it’s sending you towards the wrong directions.

This is the method I used for calculating the movement direction, so shoutout to them.

1 Like

I’m very sorry that I didn’t read your post properly :). I’ll figure it out after I have tested it

1 Like

I would use HumanoidRootPart’s look vector instead of detecting the player’s moving direction.

I’ve tried that, yes. It comes out with the same result as the other method.
I’m trying to let the player dash towards the direction they’re walking towards, regardless if they are in mouse lock camera or free camera.

If the player is in mouse lock, their character faces where ever the camera is facing. If they hold S and dash, they should perform a side dash as their character is walking to the left but facing forwards.
If the player is in free camera, their character faces the direction they’re moving towards, regardless of where the camera is facing. If they hold S and dash, they should perform a forward dash as their character is walking and facing to the left.

Again, I believe the X and Z values might be a bit wrong. I just don’t know how to fix it as I am relatively new to this stuff.

I made this code:

local currentPosition
mouse.KeyDown:Connect(function(key)
	if key == "q" then
        repeat
		   currentPosition = game.Players.LocalPlayer.Character.HumanoidRootPart.Position
           wait()
        until game.Players.LocalPlayer.Character.HumanoidRootPart:FindFirstChildOfClass("BodyVelocity")
	end
end)
mouse.KeyUp:Connect(function(key)
	if key == "q" then
		local bodyVelocity = Instance.new("BodyVelocity", game.Players.LocalPlayer.Character.HumanoidRootPart)
		bodyVelocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
		bodyVelocity.Velocity = (game.Players.LocalPlayer.Character.HumanoidRootPart.Position - currentPosition).unit*Vector3.new(1, 0, 1)*50
		wait(.25)
		bodyVelocity:Destroy()
		bodyVelocity = nil
	end
end)

Hope you know how it works because I’m too lazy to explain :slight_smile:

1 Like

Its actually pretty easy once you get the hang of it. What you have to do is to use the Cameras CFrame as the plane of movement instead of the global plane.

You can create the cameras relative forward direction by getting the cameras lookVector and “flooring” it. I like to call it that.

local Camera = workspace.CurrentCamera
local FLOOR_VECTOR = Vecter3.new(1,0,1) -- Flooring means ignoring Y axis
-- In a loop somewhere
local CameraLookDirection = (Camera.LookVector * FLOOR_VECTOR).Unit 

You have the cameras look direction

Now all you have to do is to create a CFrame based on that look Vector

local ZERO_VECTOR = Vector3.new()
local CameraRelativeCFrame = CFrame.lookAt(ZERO_VECTOR,CameraLookDirection)

Then you can use the new CFrames properties in order to apply the force

local Speed = 10
local MoveVector = CameraRelativeCFrame.CFrame:VectorToObjectSpace(Humanoid.MoveDirection).Unit * Speed

One thing to note is that BodyVelocity is legacy. I recommend not using body movers any more as there are better alternatives now.

Character.HumanoidRootPart:ApplyImpulse(MoveVector)

Link:
Impulse: BasePart | Roblox Creator Documentation
LinearVelocityConstraint: https://developer.roblox.com/en-us/api-reference/class/LinearVelocityConstraint
CFrameRelativeSpace: Object and World Space | Roblox Creator Documentation

Also small note(please don’t be offended) if your code looks repetitive like this >

if math.abs(movementDirection.X) > math.abs(movementDirection.Z) then
	if movementDirection.X < 0 then
		dashAbility(movementDirection.X, 0)
	elseif movementDirection.X > 0 then
		dashAbility(movementDirection.X, 0)
	end
elseif math.abs(movementDirection.X) < math.abs(movementDirection.Z) then
	if movementDirection.Z < 0 then
		dashAbility(movementDirection.X, movementDirection.Z)
	elseif movementDirection.Z > 0 then
		dashAbility(0, movementDirection.Z)
	end
else end

you are probably doing something wrong

3 Likes

Thank you for all of the research, but the problem is still occurring.

01c22d416be78f140696dab69e1c30df(1)

I’m sure your method of calculating the movement vector is better, but I don’t think that was the problem.

Also small note(please don’t be offended) if your code looks repetitive like this you are probably doing something wrong

I am 99.9% sure that bit of code is where the problem is coming from. I’ve tried many things, but to no avail. I know how the code works, I just don’t know how to work it as I kind of just copied and pasted it…

Sorry I wasn’t supposed to put that in there.

You were actually supposed to put the raw input in there.

local MoveVector = Vector3new(	-- I usually do this everyframe but you can change it to be event based
		0 + (UserInputService:IsKeyDown(Enum.KeyCode.D) and 1 or 0) + (UserInputService:IsKeyDown(Enum.KeyCode.A) and -1 or 0) ,
		0,
		0 + (UserInputService:IsKeyDown(Enum.KeyCode.W) and -1 or 0) + (UserInputService:IsKeyDown(Enum.KeyCode.S) and 1 or 0) 
	)

Sorry about that. This is what I use to get the move vector. Sorry my fault.

1 Like

Alright, this is the updated code:

local floorVector = Vector3.new(1, 0, 1)
local cameraLookDirection = (camera.CFrame.LookVector * floorVector).Unit
		
local zeroVector = Vector3.new()
local cameraRelativeCFrame = CFrame.lookAt(zeroVector, cameraLookDirection)
		
local directionVector = Vector3.new(
	0 + (userinputService:IsKeyDown(Enum.KeyCode.D) and 1 or 0) + (userinputService:IsKeyDown(Enum.KeyCode.A) and -1 or 0),
	0,
	0 + (userinputService:IsKeyDown(Enum.KeyCode.W) and -1 or 0) + (userinputService:IsKeyDown(Enum.KeyCode.S) and 1 or 0) 
)
		
local moveVector = cameraRelativeCFrame:VectorToObjectSpace(directionVector).Unit * dashSpeed
dashAbility(moveVector)

I believe I did it right, it almost works perfectly. When the camera is facing east and south the movement directions are reversed, but just adding a negative symbol somewhere would probably fix that. Thank you!

Another question, how can I prevent the player from going diagonal in mouse lock? Just have them be able to dash in only four directions?

Oh sorry, I didn’t even notice your reply. It actually did work, thank you! :sweat_smile:
This actually really helps cause I want this to work across all platforms.

If you’ve read my last reply, though, I still am wondering how I could prevent the player from dashing diagonally. This is really only a problem when using mouse lock, as in free camera you really can only dash forwards.

ab1817c4f7fe01dce16b440382d1f2e5

Edit: Oh yea, and how can you determine which direction they are moving towards? So that I can play dashing animations.

local script btw

local Character = script.Parent
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid = Character:WaitForChild("Humanoid")
local Debri = game:GetService("Debris")

game:GetService("UserInputService").InputBegan:Connect(function(IPO,GPE)
	if GPE then return end
	if IPO.KeyCode == Enum.KeyCode.R then
		local BV = Instance.new("BodyVelocity")
		BV.MaxForce = Vector3.new(math.huge,0,math.huge)
		BV.Velocity = Vector3.new(Humanoid.MoveDirection.X,0,Humanoid.MoveDirection.Z)*200
		BV.Parent = RootPart
		Debri:AddItem(BV,0.1)
	end
end)