How would I change the direction of the Body Velocity on based off the orientation of a part?

I used the Run Service to change the Body Velocity to the Player’s Look Vector so they can control it. There’s one problem with this and it’s if they run into a wall they won’t stop. How would I detect their velocity and check if it is lower than a certain number forcing them to stop Wall Running?

This is how it looks like in game:

You still want the code? After this or no?

Send me the code to your most recent video, that would be more helpful.

Also I got no idea how to do the debounce or cds on this because what I’ve tried isn’t working.:sob:



-- !strict

-- Services
local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local RS = game:GetService("ReplicatedStorage")

-- Player
local Players = game:GetService("Players")
local Player: Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HRP = Character:WaitForChild("HumanoidRootPart")
local Torso = Character:WaitForChild("Torso")
local Humanoid = Character:WaitForChild("Humanoid")
local Camera = workspace.CurrentCamera

local WallRunFolder = RS.Storage.Animations.Movement.WallRun

local AnimWallRunL = Humanoid:LoadAnimation(WallRunFolder.WallRunL)
local AnimWallRunR = Humanoid:LoadAnimation(WallRunFolder.WallRunR)

local AnimWallJumpL = Humanoid:LoadAnimation(WallRunFolder.WallJumpL)
local AnimWallJumpR = Humanoid:LoadAnimation(WallRunFolder.WallJumpR)
-- 
--[ Settings ]--
local Debug = true
local RayLength = 3.5
local TimeDelay = 0.2
local EndTime = 10 
local HoldingSpace = false
local NoPart = false

local raycastParmas = RaycastParams.new()
raycastParmas.FilterType = Enum.RaycastFilterType.Exclude
raycastParmas.FilterDescendantsInstances = {Character} -- Add your character to this if you don't want to detect walls for your character
raycastParmas.IgnoreWater = true 


local function DebugAttatchment(Position: Vector3) -- Using An Attachment to detect Where the wall is. (Debugging)
	if not Debug then return end

	local DebugAttachment = Instance.new("Attachment") 
	DebugAttachment.Visible = true

	DebugAttachment.CFrame = CFrame.new(Position)
	DebugAttachment.Parent = workspace.Terrain

	task.delay(5, function()
		DebugAttachment:Destroy()
	end)

	print("Wallrun began at "..tostring(Position))
end

local function LeftWallCheck() -- Checks if There is a wall to your Left.
	return workspace:Raycast(HRP.Position, -HRP.CFrame.RightVector * RayLength, raycastParmas)
end

local function RightWallCheck() -- Checks if There is a wall to your Right.
	return workspace:Raycast(HRP.Position, HRP.CFrame.RightVector * RayLength, raycastParmas)
end

local function FloorCheck() -- Checking If you are on the floor or not.
	return workspace:Raycast(HRP.Position, -HRP.CFrame.UpVector * RayLength, raycastParmas)
end



--[ Main Functions ]--
UIS.InputBegan:Connect(function(input,gpe)
	if gpe then return end

	if input.KeyCode == Enum.KeyCode.Space then
		HoldingSpace = true
	end
end)

UIS.InputEnded:Connect(function(input,gpe)
	if gpe then return end

	if input.KeyCode == Enum.KeyCode.Space then
		HoldingSpace = false
	end
end)

function WallRunCD(Debounce: boolean)
	print ("CoolDowns")
	local CD = 1000
	Debounce = true
	task.wait(CD)
	Debounce = false
	
end

function WallRun()
	if not LeftWallCheck() and not RightWallCheck()  then return end -- needs to go through these casts first.

	local Speed = Humanoid.WalkSpeed
	local IsWallRunning = false
	local WallRunL = false
	local WallRunR = false

	local DebounceR = false
	local DebounceL = false

	if Speed > 20 then -- can't wallrun if no speed
		print (Speed)
		if LeftWallCheck() then
			print (HoldingSpace)
			if IsWallRunning or DebounceL or not HoldingSpace then print ("Wall Running or On Debounce or Not Holding Space") return end
			if DebounceL then return end

			DebugAttatchment(LeftWallCheck().Position)
			IsWallRunning = true
			WallRunL = true

			Humanoid.AutoRotate = false
			Humanoid:ChangeState(Enum.HumanoidStateType.Climbing)		

			local bv = Instance.new("BodyVelocity",HRP)
			bv.MaxForce = Vector3.new (math.huge,math.huge,math.huge)
			
			RunService.RenderStepped:Connect(function()
				task.wait(.1)
				if LeftWallCheck() == nil and IsWallRunning then

					bv:Destroy()
					if AnimWallRunL then
						AnimWallRunL:Stop(.5)
					end

					IsWallRunning = false
					WallRunL = false
					Humanoid.AutoRotate = true
				elseif IsWallRunning and LeftWallCheck() ~= nil then
					bv.Velocity = HRP.CFrame.LookVector * Speed + -HRP.CFrame.UpVector * 15
				end		
			end)
			
			AnimWallRunL:Play()
			
			--
			Humanoid.StateChanged:Connect(function(old,new)
				if new == Enum.HumanoidStateType.Landed and FloorCheck() == nil then
					bv:Destroy()
					if AnimWallRunL then
						AnimWallRunL:Stop(.5)
					end
					
					IsWallRunning = false
					WallRunL = false
					Humanoid.AutoRotate = true
				end
			end)

			--

			UIS.InputEnded:Connect(function(input,gpe)
				if gpe then return end
				if input.KeyCode == Enum.KeyCode.Space and IsWallRunning then
					print ("Wall Jumped")
					bv:Destroy()
					repeat 
						HRP.Velocity = HRP.CFrame.RightVector * 40  + HRP.CFrame.UpVector * 40
						task.wait(.1)
					until IsWallRunning == false
					--
					if AnimWallRunL then
						AnimWallRunL:Stop(.5)
					end
					
					
					AnimWallJumpL:Play()

					Humanoid.AutoRotate = true 
					IsWallRunning = false
					WallRunL = false
				end
			end)
			
			if not WallRunL then
				WallRunCD(DebounceL)
				return
			end
			
			task.wait(EndTime)
			Humanoid.AutoRotate = true 
			
			if bv then
				bv:Destroy()
			end
			
			if AnimWallRunL then
				AnimWallRunL:Stop()
			end
			WallRunL = false
			WallRunCD(DebounceL)
			
			
			


		elseif RightWallCheck() then
			-- Add after finishing Wall Run
		end

	end
end


UIS.InputBegan:Connect(function(Input, GPE)
	if GPE then return end
	if Input.KeyCode == Enum.KeyCode.A or Enum.KeyCode.D then
		if not Humanoid:GetState(Enum.HumanoidStateType.Freefall) then return end
		WallRun()
	end
end)

UIS.InputBegan:Connect(function()
	Camera.ChildAdded:Connect(function(Child)
		if Child.Name == "Viewmodel" then
			raycastParmas.FilterDescendantsInstances = {Character,Child}
		end
	end)
end)



At what point do you want them to stop? What velocity do you want them to be above (x y or z, or multiple)

After the Body Velocity is destroyed

Doesn’t destroying the body velocity do that for you? Whenever I use body velocity and destroy it I stop moving.

I made a RayCast going in the Look Vector direction then if the distance was lower or equal than 2 it would stop Wall Running. Don’t worry about that anymore. I just need help on the cool downs because I genuinely have no idea how to do them.

It appears that the method you’re using to set the debounce doesn’t work as you’re thinking. When I tried testing it, trying to set a supplied debounce to true from a function (when supplying something else) does not work. It would be better to supply an argument in which is coded to specifically change one variable. I would also recommend that you make the debounces public (and put them under specific users) or move them into some player specific loop in which your debounces also are.

My example for using a ‘player specific loop’ would be doing:
debounceL[player.UserId] = true or something along those lines.

I think the better approach would be to move this function into the part where those variables currently are and make specific loops where you supply “L” or “R” which then if it’s L it debounces the left debounce and so on.

It’s a local script. And it gives a error if I try doing DebounceL[player.UserId] = true

If it’s a local script then you don’t have to deal with any of the things that result from a server script. You can move the variables to the top of the script and it will not impact anything.

Yeah but how do I add cool downs from the server script?
This is the code that I tried using but it didn’t really work at all. Then I fired the remote event every time I wanted a cooldown (after bv gets destoryed and anims stop, etc.)


-- Events

local RS = game:GetService("ReplicatedStorage")

local Cooldowns = RS.Storage.RemoteEvents.MISCEvents.Cooldowns
local CooldownList = {}

Cooldowns.OnServerEvent:Connect(function(player : Player, CD: number, Debounce: boolean)
	print("cooldown remote")
	if not CooldownList[player.UserId] then
		CooldownList[player.UserId] = true
		print("skibdii taxxxxx")
		
		
		Debounce = true
		print(Debounce)
		wait(CD)
		Debounce = false
		CooldownList[player.UserId] = nil
	end
end)

If you haven’t already, check for errors in this script. You should also check and make sure you are getting the correct number/bool for each of the arguments you are receiving. This is what I’m doing which seems to be working:

local CooldownList = {}
game.Players.PlayerAdded:Connect(function(Player:Player)
	print("cooldown")
	cooldown(Player)
	wait(7)
	cooldown(Player)
end)


function cooldown(Player)
	if not CooldownList[Player.UserId] or CooldownList[Player.UserId] == false then
		CooldownList[Player.UserId] = true
		print(CooldownList)
		task.wait(5)
		CooldownList[Player.UserId] = nil
		print(CooldownList)
	end
end
1 Like