Creating an advanced ledge climbing system

I want to make a Ledge Climbing System for my game

I don’t want someone to just make a system for me as I prefer to actually understand things, but I just want someone to help me start because I have no clue where to even begin in making system like this. I have animations finished already. I’ve tried raycasting with the character’s head, but it doesn’t properly detect ledge parts.

I’ve tried looking for tutorials and searching on the DevForum, but I’ve been unsuccessful

Here is a video of what I’m trying to achieve, any help is appreciated!

I haven’t made anything like this myself, but you could possibly use raycasts.
For example, if a raycast with a short distance, casted from the head / torso area hits, while an identical on casted from above the head doesn’t, then the ledge climbing could be activated.

1 Like

Roblox somewhat has this functionality already with climbing.

I’ll test out a few things and edit this post after I’ve experimented.

Edit:
I’ve found out how to do this. However, it’s not really advanced and is quite basic. Here’s what I did:

  1. Create a LocalScript in StarterCharacterScripts
  2. Raycast from the front of the character down. If the part’s name is ‘ledge’ then you weld the root part to the ledge part.
  3. Get the dot product of the root’s look vector and the humanoid move direction.
  4. Add to the CFrame of the weld, in object space, the dot product.
  5. If the weld is enabled the next frame, set the part0 to nil and disable it.

Then you are done!

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local root = humanoid.RootPart

local runService = game:GetService("RunService")

local raycastOffset = CFrame.new(0, 4, -1) * CFrame.Angles(-math.pi/2, 0, 0)

local params = RaycastParams.new()
params.FilterDescendantsInstances = {character}
params.IgnoreWater = true

local weld = Instance.new("Weld")
weld.Part1 = root
weld.Parent = root

--local cam = workspace.CurrentCamera

runService.RenderStepped:Connect(function(dt)
	if weld.Enabled then
		weld.Enabled = false
		weld.Part0 = nil
	end
	local rootCF = root.CFrame
	if humanoid.Jump then
		root:ApplyImpulse(rootCF.ZVector * root.AssemblyMass)
		return
	end
	local rayCF = rootCF * raycastOffset
	local rayPos = rayCF.Position
	local rayDir = rayCF.LookVector * 6
	local result = workspace:Raycast(rayPos, rayDir, params)
	if result and result.Instance then
		if result.Position.Y > rootCF.Position.Y + 1.5 then return end
		if result.Instance.Name == "ledge" then
			weld.Enabled = true
			local move = humanoid.MoveDirection:Dot(rootCF.LookVector)
			weld.C0 = result.Instance.CFrame:ToObjectSpace(rootCF) * CFrame.new(0, dt*move*5, -dt*move)
			weld.Part0 = result.Instance
			humanoid:ChangeState(Enum.HumanoidStateType.Climbing)
		end
	end
end)

Of course, there are essential pieces missing, such as animations. In my case, I tested this with R15 (it should work with R6 too), and I needed to add a check so that the player was actually climbing the ledge and not jumping under it.

8 Likes