Lets not waste time and get straight into it!
How my wall climb/mantling works is by using Raycasts
I have a function that sets up attachments inside the humanoidrootpart
something like this
now everytime the player tries to jump we will shoot ray from each attachment to the lookvector
giving us a result like this
We can check how many rays detected a part and then decide if we should perform a mantle or wall climb (something like this
now for actually performing the action
many people use gyro and stuff
while some is accurate many arent
we wont be using gyro
to perform the action
we will check how many rays detected a part from bottom to top
then we just simple teleport the player on thr Y axis based on that information
then we just simply teleport it 5 studs ahead
Giving us a result like this
This is the final script:
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local hrp: Part = character:WaitForChild("HumanoidRootPart")
local humanoid: Humanoid = character:WaitForChild("Humanoid")
-- Configure Attachments
local attachments = {}
local rayDistance = 5
local rayOriginOffset = 1
local rayVisualDuration = .5
local function createAttachments()
for i = -4, 5 do
local attachment = Instance.new("Attachment")
attachment.Position = Vector3.new(0, i * rayOriginOffset, 0)
attachment.Visible = true
attachment.Parent = hrp
table.insert(attachments, attachment)
end
end
local function createRayVisual(startPos, endPos)
local rayPart = Instance.new("Part")
rayPart.Anchored = true
rayPart.CanCollide = false
rayPart.Material = Enum.Material.Neon
rayPart.Color = Color3.new(1, 0, 0)
rayPart.Size = Vector3.new(0.1, 0.1, (endPos - startPos).Magnitude)
rayPart.CFrame = CFrame.new(startPos, endPos) * CFrame.new(0, 0, -(endPos - startPos).Magnitude / 2)
rayPart.Parent = workspace
game.Debris:AddItem(rayPart, rayVisualDuration)
end
local function castRays()
local hitCount = 0
local results = {}
for _, attachment in pairs(attachments) do
local rayOrigin = attachment.WorldPosition
local rayDirection = hrp.CFrame.LookVector * rayDistance
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
local rayEndPos = raycastResult and raycastResult.Position or (rayOrigin + rayDirection)
createRayVisual(rayOrigin, rayEndPos)
if raycastResult then
hitCount = hitCount + 1
table.insert(results, true)
else
table.insert(results, false)
end
end
return hitCount, results
end
local function checkActionType(hitCount, results)
if hitCount <= 5 and hitCount > 0 then
return "Mantle"
elseif hitCount > 5 and hitCount <= 9 then
return "WallClimb"
else
return nil
end
end
local function executeAction(hitCount, actionType)
local climbHeight = hitCount * rayOriginOffset
local forwardMovement = hrp.CFrame.LookVector * 5
if actionType == "Mantle" then
print("Performing Mantle!")
hrp.Anchored = true
hrp.CFrame = hrp.CFrame + Vector3.new(0, climbHeight, 0)
hrp.CFrame = hrp.CFrame + forwardMovement
hrp.Anchored = false
elseif actionType == "WallClimb" then
print("Performing Wall Climb!")
hrp.Anchored = true
hrp.CFrame = hrp.CFrame + Vector3.new(0, climbHeight, 0)
hrp.CFrame = hrp.CFrame + forwardMovement
hrp.Anchored = false
end
end
local function onJumpRequest()
local hitCount, rayResults = castRays()
local actionType = checkActionType(hitCount, rayResults)
if actionType then
executeAction(hitCount, actionType)
else
humanoid.JumpPower = 50
humanoid.Jump = true
wait(1)
humanoid.JumpPower = 0
end
end
game.UserInputService.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Space then -- On spacebar press
onJumpRequest()
end
end)
humanoid.JumpPower = 0
createAttachments()
Ofc this have its flaws cuz I made it in 10 mins or smt
like it will act weirdly with parts like this
I highly doubt it will bug with meshes
you can use this as a base for ur mantling/wallclimb stuff
one more thing,
I am using a single part for everything so idk how it will work with full character bodies
Goodluck.