Optimize Climb Script

Hello, I copied and pasted :slight_smile: an open source climb system and I made some changes like it always checks for walls instead of a desired key, but this causes a lot of lag.

I want to try improve the code so it’s not always shooting raycasts instead only when some condition is met.

I tried using humanoid.Running, but it didn’t really work so if there is any other possible way please suggest.

Code:

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")

local climbAni = animator:LoadAnimation(script:WaitForChild("Climb R6"))
local speed = 10

local params = RaycastParams.new()
params.FilterDescendantsInstances = {character}
params.FilterType = Enum.RaycastFilterType.Exclude

local attach = Instance.new("Attachment")
attach.Parent = rootPart

local move = Instance.new("LinearVelocity")
move.Enabled = false
move.MaxForce = math.huge
move.Attachment0 = attach
move.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
move.VectorVelocity = Vector3.new()
move.Parent = attach


local gyro = Instance.new("AlignOrientation")
gyro.Enabled = false
gyro.Mode = Enum.OrientationAlignmentMode.OneAttachment
gyro.RigidityEnabled = true
gyro.Attachment0 = attach
gyro.Parent = attach

local result
local canClimb = true

local XAxis = {
	0; --Left
	0 --Right
}
local YAxis = {
	0; --Up
	0 --Down
}

function down(KEY)
	return UserInputService:IsKeyDown(Enum.KeyCode[KEY])
end

local function playAnimation()
	if move.VectorVelocity ~= Vector3.new(0, 0, 0) and result then
		climbAni:AdjustSpeed(1)
	elseif result then
		climbAni:AdjustSpeed(0)
	end
end

RunService.Heartbeat:Connect(function()
	if canClimb and result ~= nil then
		if rootPart.Position.Y >= result.Instance.Position.Y + result.Instance.Size.Y/2 or rootPart.Position.Y <= 2 then
			canClimb = false
			rootPart.CFrame += rootPart.CFrame.LookVector+rootPart.CFrame.UpVector*2
		end

		local sideOrigin = rootPart.Position + rootPart.CFrame.LookVector
		local sideDirection = (down("D") and -rootPart.CFrame.RightVector) or rootPart.CFrame.RightVector
		
		local hit = workspace:Raycast(sideOrigin, sideDirection, params)
		if hit then
			gyro.CFrame = CFrame.lookAt(hit.Position+(hit.Normal/2), hit.Position)
			rootPart.CFrame = CFrame.lookAt(hit.Position+(hit.Normal/2), hit.Position)
		end
	end
end)

do
	local inputTask = {
		[Enum.KeyCode.W] = function(state)
			YAxis[1] = (state and 1) or 0
		end;

		[Enum.KeyCode.S] = function(state)
			YAxis[2] = (state and 1) or 0
		end;

		[Enum.KeyCode.A] = function(state)
			XAxis[1] = (state and 1) or 0
		end;

		[Enum.KeyCode.D] = function(state)
			XAxis[2] = (state and 1) or 0
		end;
		
		[Enum.KeyCode.Space] = function(state)
			if state then
				canClimb = false
			end
		end;
	}
	
	
	UserInputService.InputBegan:Connect(function(input: InputObject)
		if inputTask[input.KeyCode] then
			inputTask[input.KeyCode](true)
		end
	end)
	
	
	UserInputService.InputEnded:Connect(function(input: InputObject)
		if inputTask[input.KeyCode] then
			inputTask[input.KeyCode](false)
		end
	end)
end

RunService.Stepped:Connect(function()
	local origin = rootPart.Position
	local direction = rootPart.CFrame.LookVector

	result = workspace:Raycast(origin, direction, params)

	if result and canClimb and result.Instance:GetAttribute("Climbable") then
		humanoid.AutoRotate = false
		humanoid.PlatformStand = true
		gyro.CFrame = CFrame.lookAt(result.Position + (result.Normal/2), result.Position)
		move.Enabled = true
		gyro.Enabled = true
		if not climbAni.IsPlaying then
			climbAni:Play()
		end

		local X = XAxis[2]-XAxis[1]
		local Y = YAxis[1]-YAxis[2]

		move.VectorVelocity = Vector3.new(X*speed, Y*speed, 0)
		playAnimation()
	elseif not canClimb and move.Enabled == true then
		humanoid.AutoRotate = true
		humanoid.PlatformStand = false
		move.Enabled = false
		gyro.Enabled = false
		result = nil
		climbAni:Stop()
		task.wait(0.5)
		canClimb = true
	end
end)

Thank you.

1 Like

Are you sure that the climbing script is what’s causing the lag? I tried the script myself and didn’t experience any performance issues.

1 Like

I have no exact proof besides that when I disable the script the game is less laggy. And I sort of assumed it was the script because I believe constantly sending raycasts can be laggy especially I plan on the game being multiplayer.

Edit: How can I test what lags my game?
Edit: I learned that another script causes lag, but I’m still curious is there any other way to improve the script if not I’ll give you solution. :slight_smile: ty

I noticed the script was slightly glitchy and after removing “elseif not canClimb and move.Enabled == true then” from the .Stepped connection and replacing it with just “else” it stopped being glitchy. Also even though you’re using raycast very often it shouldn’t affect performance that much because the distance is very short.

1 Like

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