--// Smooth Wall + Edge Transition Script --// LocalScript in StarterPlayerScripts local Players = game:GetService("Players") local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local player = Players.LocalPlayer local char = player.Character or player.CharacterAdded:Wait() local hum = char:WaitForChild("Humanoid") local root = char:WaitForChild("HumanoidRootPart") local wallMode = false local wallCheckDist = 7 local floorCheckDist = 6 local climbSpeed = 24 local stickForce = 61 local rotateSpeed = 0.4 -- Toggle with X UserInputService.InputBegan:Connect(function(input, gpe) if gpe then return end if input.KeyCode == Enum.KeyCode.X then wallMode = not wallMode print(wallMode and "Wall Mode ON" or "Wall Mode OFF") if not wallMode then hum:ChangeState(Enum.HumanoidStateType.Freefall) end end end) RunService.Heartbeat:Connect(function(dt) if not wallMode then return end if not root or not hum then return end local rayParams = RaycastParams.new() rayParams.FilterDescendantsInstances = {char} rayParams.FilterType = Enum.RaycastFilterType.Exclude -- Forward ray to find walls local forwardRay = workspace:Raycast(root.Position, root.CFrame.LookVector * wallCheckDist, rayParams) -- Downward ray to detect ground when transitioning local downRay = workspace:Raycast(root.Position, -root.CFrame.UpVector * floorCheckDist, rayParams) local surfaceHit = forwardRay or downRay if surfaceHit then local normal = surfaceHit.Normal local moveDir = hum.MoveDirection -- Calculate alignment local forward = -normal local up = Vector3.new(0, 1, 0) local right = forward:Cross(up) up = right:Cross(forward) -- If we're near a floor edge (surface facing mostly upward) if math.abs(normal.Y) > 0.6 then -- Smoothly reset upright when walking over ledge local uprightCF = CFrame.fromMatrix(root.Position, right, Vector3.new(0,1,0)) root.CFrame = root.CFrame:Lerp(uprightCF, rotateSpeed) else -- Align to wall local wallCF = CFrame.fromMatrix(root.Position, right, up) root.CFrame = root.CFrame:Lerp(wallCF, rotateSpeed) end -- Movement logic if moveDir.Magnitude > 0.05 then -- Project onto surface plane so we move along it local surfaceMove = (moveDir - normal * moveDir:Dot(normal)).Unit local climbVel = surfaceMove * climbSpeed -- Add upward bias when wall is steep if normal.Y < 0.5 then climbVel += up * (climbSpeed * 0.6) end root.AssemblyLinearVelocity = climbVel - normal * stickForce else root.AssemblyLinearVelocity *= 0.8 end else hum:ChangeState(Enum.HumanoidStateType.Freefall) end end)