local UserInputService = game:GetService(“UserInputService”)
local ContextActionService = game:GetService(“ContextActionService”)
local RunService = game:GetService(“RunService”)
local TweenService = game:GetService(“TweenService”)
local Debris = game:GetService(“Debris”)
local GuiService = game:GetService(“GuiService”)

local player = game.Players.LocalPlayer
local character = player.Character
local camera = workspace.CurrentCamera
local humanoid = character:WaitForChild(“Humanoid”)
local rootPart = character:WaitForChild(“HumanoidRootPart”)
local head = character:WaitForChild(“Head”)

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

local vaultMoveNumber = 10
local canVault = true
local canMove = true
local vaultConnection = nil
local ledgePart = nil



local function partCheck(ledge)
local vaultPartCheck = workspace:Raycast(ledge.Position + Vector3.new(0, -1, 0) + ledge.LookVector * 1, ledge.UpVector * 3, raycastParams)
if vaultPartCheck == nil then
return true
else
return false
end
end

local function vaultMove(direction, anim)
local moveRay = workspace:Raycast(head.CFrame.Position, head.CFrame.RightVector * direction + head.CFrame.LookVector * 8, raycastParams)
if moveRay then
if moveRay.Instance then
end
else
local turnRay = workspace:Raycast(head.CFrame.Position + Vector3.new(0, -1, 0) + head.CFrame.RightVector * direction, head.CFrame.RightVector * -direction + head.CFrame.LookVector * 2, raycastParams)
if turnRay then
if turnRay.Instance then
end
end
end
end

humanoid:GetPropertyChangedSignal(“MoveDirection”):Connect(function()
if canMove then
if (humanoid.MoveDirection:Dot(camera.CFrame.RightVector) > .7) and not canVault then
vaultMove(vaultMoveNumber, “Right”)
end

if (humanoid.MoveDirection:Dot(-camera.CFrame.RightVector) > .7) and not canVault then
vaultMove(-vaultMoveNumber, “Left”)
end
end
end)

local function detectLedge()
if canVault and (humanoid:GetState() == Enum.HumanoidStateType.Freefall or humanoid:GetState() == Enum.HumanoidStateType.Jumping) then
local vaultCheck = workspace:Raycast(rootPart.CFrame.Position, rootPart.CFrame.LookVector * 5, raycastParams)
if vaultCheck then
if vaultCheck.Instance then
local localPos = vaultCheck.Instance.CFrame:PointToObjectSpace(vaultCheck.Position)
local localLedgePos = Vector3.new(localPos.X, vaultCheck.Instance.Size.Y/2, localPos.Z)
local ledgePos = vaultCheck.Instance.CFrame:PointToWorldSpace(localLedgePos)
local ledgeOffset = CFrame.lookAt(ledgePos, ledgePos - vaultCheck.Normal)

local magnitude = (ledgePos - head.Position).Magnitude
if magnitude < 5 then
if partCheck(ledgeOffset) then
canVault = false
canMove = false

ledgePart = Instance.new(“Part”)
ledgePart.Parent = workspace
ledgePart.Anchored = true
ledgePart.Size = Vector3.one
ledgePart.CFrame = ledgeOffset + Vector3.new(0, -2, 0) + ledgeOffset.LookVector * -1
ledgePart.CanQuery = false
ledgePart.CanCollide = false
ledgePart.CanTouch = false
ledgePart.Transparency = 1

vaultConnection = RunService.RenderStepped:Connect(function(dt)
rootPart.Anchored = true
humanoid.AutoRotate = false
rootPart.CFrame = rootPart.CFrame:Lerp(CFrame.lookAt(ledgePart.Position, (ledgePart.CFrame * CFrame.new(0, 0, -1)).Position), .25)
humanoid:ChangeState(Enum.HumanoidStateType.Seated)
end)
end
end
end
end
elseif not canVault then
canVault = true
canMove = true
humanoid.AutoRotate = true
rootPart.Anchored = false
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)

if vaultConnection then
vaultConnection:Disconnect()
end

if ledgePart then
ledgePart:Destroy()
end
end
end

UserInputService.InputBegan:Connect(function(input, gp)
if (input.KeyCode == Enum.KeyCode.ButtonA or input.KeyCode == Enum.KeyCode.Space) then
detectLedge()
end
end)

if UserInputService.TouchEnabled and not UserInputService.KeyboardEnabled and not UserInputService.MouseEnabled and not UserInputService.GamepadEnabled and not GuiService:IsTenFootInterface() then
local jumpButton = player.PlayerGui:WaitForChild(“TouchGui”):WaitForChild(“TouchControlFrame”):WaitForChild(“JumpButton”)
jumpButton.Activated:Connect(function()
detectLedge()
end)
end

Consolidate raycasts into a single call where possible. Repeated calculations like head.Position and camera.CFrame.RightVector are done multiple times, so store these in local variables to avoid redundant calculations. The state management of canVault and canMove can be improved, ensuring they toggle correctly; implement state machine or use flags that are easy to follow. Consider TweenService for smoother animations instead of CFrame:Lerp. Break down large functions into smaller, reusable functions. Variables like ledgePart that may not be required as a global; Make them local to the scope they’re needed in.