How to make a descendible ladder?

Hello everyone,

I was working on a game of mine and ran across a problem. I am currently making a zone with heavy use of ladders in a “scaffolding” type theme, but I noticed that it would be extremely difficult for players to descend the ladders I have placed. Does anyone have any ideas for how to solve this problem?


This is an example of the kind of ladder stuff I am doing

1 Like

Hi CannibalCooper,

Why do you think it would be difficult for players to descend the laters? May you please elaborate?

2 Likes

There is a fall damage mechanic in the game and no shiftlock or first person to assist. I am using to use the default roblox climbing mechanics

2 Likes

Perhaps you could make a safety cage around the ladder… not sure if it would fit the theme though.

2 Likes

I can’t think of any building-based solutions for this.

I wrote you some code to solve this. Basically it smoothly makes the player face the ladder when they’re falling.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local localPlayer = Players.LocalPlayer

local ladder = script.Parent
-- Add an ObjectValue with the value set to the trigger part
-- to the script or use the ladder as a default
local triggerPart = script.Parent


local duration = 3
local activationDistanceMax = 10
local activationDistanceMin = 0.5
local rotationSpeedMax = 0.8 -- value between 0 and 1
local rotationAcceleration = 1

local rotationSpeed = 0
local startTime = 0
local connection = nil
local function startConnection()
	startTime = tick()
	if connection then return end

	connection = RunService.RenderStepped:Connect(function(step)
		if tick() > startTime + duration then
			connection:Disconnect()
			connection = nil
			local humanoid = localPlayer.Character and localPlayer.Character:FindFirstChild("Humanoid")
			if humanoid then
				humanoid.AutoRotate = true
			end
			return
		end

		local character = localPlayer.Character
		if not character then return end

		local humanoid = character:FindFirstChild("Humanoid")
		local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")

		if (not humanoid) or (not humanoidRootPart) then return end

		local hrpPosition = humanoidRootPart.Position
		local horizontalDistance = (Vector2.new(hrpPosition.X, hrpPosition.Z) - Vector2.new(ladder.Position.X, ladder.Position.Z)).Magnitude
		
		local humanoidState = humanoid:GetState()
		local correctState = (humanoidState == Enum.HumanoidStateType.Freefall) or (humanoidState == Enum.HumanoidStateType.Jumping)
		
		if horizontalDistance < activationDistanceMax and  horizontalDistance > activationDistanceMin and correctState then
			humanoid.AutoRotate = false
			
			rotationSpeed += rotationAcceleration * step
			if rotationSpeed > rotationSpeedMax then
				rotationSpeed = rotationSpeedMax
			end
			
			local relativeLadderPosition = ladder.Position + Vector3.new(0, hrpPosition.Y - ladder.Position.Y, 0)
			local goalCFrame = CFrame.lookAt(hrpPosition, relativeLadderPosition)
			humanoidRootPart.CFrame = humanoidRootPart.CFrame:Lerp(goalCFrame, rotationSpeed)
		else
			humanoid.AutoRotate = true
			
			rotationSpeed = 0
		end




	end)
end

-- When the trigger part is hit, make it so the player faces
-- towards the ladder so it's easy to climb
local function onTouched(part)
	local character = part.Parent
	if not character then return end

	local player = Players:GetPlayerFromCharacter(character)
	if not player or not (player == localPlayer) then return end

	startConnection()
end

local touchedConnection
local function createConnection()
	if touchedConnection then
		touchedConnection:Disconnect()
	end
	touchedConnection = triggerPart.Touched:Connect(onTouched)
end

createConnection()

-- Steaming enabled can be such a pain
script.ChildAdded:Connect(function(child)
	if child.Name == "Trigger" then
		triggerPart = child.Value
		if not triggerPart then
			
			while not triggerPart do
				triggerPart = child.Value
				task.wait(0.1)
			end
		end
		createConnection()
	end
end)

(Goes inside the ladder in a Script set to Client RunContext)

I made a place file since setting up the script run context can be a little advanced, and it makes it easier to test it out.

AutoLadderRotate.rbxl (59.0 KB)

Some GIFs of what it does:

ezgif.com-video-to-gif (2)

ezgif.com-video-to-gif (4)

I would recommend trigger parts (the orange part in the gifs above for the second ladder). The trigger parts make it so if the player passes through the area of the part, if they fall in the next few seconds close to the ladder they face towards it. The default is using the ladder as the trigger part, but that doesn’t work well if the player jumps over the ladder.

To make a trigger part, add an ObjectValue named “Trigger” to the script and set the ObjectValue’s Value to the trigger part. The trigger part should be invisible and non-collide.

2 Likes

From what I’ve seen in games, they usually have the ladder go on the inside of the scaffolding and a hole in the scaffolding floor for the player to go through. That way the player can walk into the ladder the proper direction. You could also use the code above if you don’t want to have to do that.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.