So I’ve been trying to make a climbing system for a while now, and I’ve run into several issues with it that I haven’t been able to solve, the main one being climbing around corners, which I haven’t been able to find any information about. There are other issues with it, which I will mention latter.
Ok, so the way that the system is set up prevents it from detecting walls angled at about 90 degrees away from the wall that the player is currently climbing on, causing the player to just fall of walls with sharp corners. The way that I tried to fix this is rotating the player 90 degrees depending on whether the player is moving to the left or to the right. The problem with this is that it looks really glitchy, and also if you stop at a corner, the player bugs out as if they’re having a seizure. I know why this happens (or at least I think I do), but I have no clue how to fix it. There’s also the fact that this method doesn’t work for climbing sharp corners angled 90 degrees towards the wall the player is currently climbing on.
Here’s an example of these things:
Yeah.
As you could see, the method that I’m using to climb around corners absolutely sucks and barely works, so I wanted to try a different method. One problem. I don’t have another method. So, that’s an issue.
I looked all over YouTube and the Devforum, but couldn’t find anything on climbing around corners and stuff like that. The closest thing that I could find were open sourced ledge grabbing systems. At first I thought, “Oh boy! I can just steal the climbing-around-corners part of these systems, and use it in my climbing system!” The problem was that my brain was waaaaaay too tiny to understand anything that was going on within the systems, so I couldn’t locate the parts responsible for climbing around corners. There’s.
That brings me to my request. I was hoping one of you big-brained developers could at least give me an example of how I should go about updating my climbing system so that players can climb around sharp corners. I would also request that someone give me some insight on how ledge grabbing systems locate the ledges of walls. I’ve looked at some code depicting this, and I know it has something to do with the ToWorldSpace and ToObjectSpace functions, but again, my brain is too small to understand it. Even after I watched a video explaining the ToWorldSpace and ToObjectSpace functions, which I now understand, I still don’t get how they have anything to do with locating the ledge of a wall.
One of the minor problems with my climbing system is that when climbing around smooth corners, the player tends to be pushed away from the wall. Eventually, the player gets pushed so far away from the wall that they end up falling off. I’ve already tried fixing this but I couldn’t , although I will probably find a solution eventually. Another minor problem with my climbing system is the fact that I got no clue what to do for when the player is moving diagonally, actually, this is probably one of the more major problems. Huh. There’s also the fact that the entire script breaks when the player dies… I’ll get to that eventually. Here’s the script for my climbing system.
local c = script.Parent
local SH = require(game.ReplicatedStorage.Statehadler) --A module that keeps track of what the player is doing
local hrp = c:WaitForChild("HumanoidRootPart")
local hum = c:WaitForChild("Humanoid")
local UIS = game:GetService("UserInputService")
local speed = 10
local Pos = {} --Postion table
local climb --Event variable
local XAxis = {
0; --Left
0 --Right
}
local YAxis = {
0; --Up
0 --Down
}
do
--Movement handler stuff
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;
}
UIS.InputBegan:Connect(function(input: InputObject)
if inputTask[input.KeyCode] then
inputTask[input.KeyCode](true)
end
end)
UIS.InputEnded:Connect(function(input: InputObject)
if inputTask[input.KeyCode] then
inputTask[input.KeyCode](false)
end
end)
end
local function StopClimbing()
--Stops the player from climbing
if climb == nil then return end
climb:Disconnect()
climb = nil
if hum:GetState() == Enum.HumanoidStateType.Climbing then
hum:SetStateEnabled(Enum.HumanoidStateType.Running, true)
hum.AutoRotate = true
hrp:FindFirstChild("climbingattachment"):Destroy()
end
end
local function CalculateDirection(startpos,endpos,object)
--Uses the Dot function to find the direction the player is moving. Probably what im most proud of in this system lol.
local product
local Dir = (endpos - startpos).Unit
if Dir:Dot(-object.CFrame.UpVector) > 0.50 then
product = "Up"
elseif Dir:Dot(object.CFrame.UpVector) > 0.50 then
product = "Down"
elseif Dir:Dot(-object.CFrame.RightVector) > 0.50 then
product = "Right"
elseif Dir:Dot(object.CFrame.RightVector) > 0.50 then
product = "Left"
end
return product
end
UIS.InputBegan:Connect(function(input,gpe)
if input.KeyCode == Enum.KeyCode.Space and SH[c].Grounded == false then
climb = game:GetService("RunService").Heartbeat:Connect(function()
local NewRaycastParams = RaycastParams.new()
NewRaycastParams.FilterType = Enum.RaycastFilterType.Exclude
NewRaycastParams.FilterDescendantsInstances = {c}
local Origin = hrp.Position
local Direction = hrp.CFrame.LookVector * 2
local Raycast = workspace:Raycast(Origin, Direction, NewRaycastParams)
if Raycast then
local climbingattachment = hrp:FindFirstChild("climbingattachment")
local movement
local gyro
if climbingattachment == nil then
--Creates all the stuff needed for climbing
climbingattachment = Instance.new("Attachment",hrp)
climbingattachment.Name = "climbingattachment"
movement = Instance.new("LinearVelocity")
movement.MaxForce = math.huge
movement.Attachment0 = climbingattachment
movement.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
movement.VectorVelocity = Vector3.new()
movement.Parent = climbingattachment
gyro = Instance.new("AlignOrientation")
gyro.Mode = Enum.OrientationAlignmentMode.OneAttachment
gyro.Attachment0 = climbingattachment
gyro.RigidityEnabled = true
gyro.Parent = climbingattachment
else
movement = climbingattachment:FindFirstChild("LinearVelocity")
gyro = climbingattachment:FindFirstChild("AlignOrientation")
end
local RaycastCFrame = CFrame.lookAt(Raycast.Position + (Raycast.Normal/2), Raycast.Position) --The orentation of the raycast postion
--Saves the last two postions the player was located at in a table
if #Pos < 2 then
table.insert(Pos,Raycast.Position)
else
table.remove(Pos,1)
table.insert(Pos,Raycast.Position)
end
gyro.CFrame = RaycastCFrame
hum.AutoRotate = false
hum:ChangeState(Enum.HumanoidStateType.Climbing)
hum:SetStateEnabled(Enum.HumanoidStateType.Running, false)
else
if hum:GetState() == Enum.HumanoidStateType.Climbing then
local Dir = CalculateDirection(Pos[2],Pos[1],hrp)
if Dir == "Up" then
StopClimbing()
hrp:ApplyImpulse(Vector3.new(0,1000,0)) --Place holder
elseif Dir == "Right" then
hrp.CFrame = hrp.CFrame:ToWorldSpace(CFrame.Angles(0,math.rad(90),0)) --Rotates player
elseif Dir == "Left" then
hrp.CFrame = hrp.CFrame:ToWorldSpace(CFrame.Angles(0,math.rad(-90),0)) --Rotates player
end
else
StopClimbing()
end
end
end)
end
end)
UIS.InputEnded:Connect(function(input,gpe)
if (input.KeyCode == Enum.KeyCode.Space or SH[c].Grounded == true) and climb ~= nil then
StopClimbing()
end
end)
game:GetService("RunService").Heartbeat:Connect(function()
--Moves the player
local climbingattachment = hrp:FindFirstChild("climbingattachment")
if hum:GetState() ~= Enum.HumanoidStateType.Climbing or climbingattachment == nil then return end
local movement = climbingattachment:FindFirstChild("LinearVelocity")
local X = XAxis[2]-XAxis[1]
local Y = YAxis[1]-YAxis[2]
movement.VectorVelocity = Vector3.new(X*speed, Y*speed, 0)
end)
Thank you in advance .