Personally I used bodygyro and just set it to the vector normal of the wall but their is definently another way to go about it
Do you have an open source so I can analyze?
- Hello, I have read this topic and used the open source that was shared. I have edited the open source to be able to switch from different walls, but I have run into a major problem. Whenever the player switches between two walls that are adjacent to each other, and create lower than a 90 degree angle, when the player tries to flip around the new wall they climbed onto, the player starts floating, and is able to climb left and right infinitely, almost as if there is a large invisible wall. The script works great at 90 degree angles, but anything lower makes this bug occur. This bug breaks many systems, like the wall jumping, and after hours of reasearch, I cannot figure out why it does this. This is the code I am using
local ppl = game:GetService("Players")
local run = game:GetService("RunService")
local uis = game:GetService("UserInputService")
local plr = ppl.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:WaitForChild("Humanoid")
local root = char:WaitForChild("HumanoidRootPart")
local spd = hum:GetAttribute("ClimbSpeed")
--// I was gonna put "state = hum:GetAttribute("ClimbState")" but attributes don't work with repeated checks.
local params = RaycastParams.new()
params.FilterDescendantsInstances = {char}
params.FilterType = Enum.RaycastFilterType.Blacklist
params.IgnoreWater = true
params.CollisionGroup = ("canClimb")
--// attachments are a most for constraints.
local attach = Instance.new("Attachment")
attach.Parent = root
--// as the name says, it's for movement while climbing
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 = root
--// you should try playing with gyro off it's funny
local gyro = Instance.new("AlignOrientation")
gyro.Enabled = false
gyro.Mode = Enum.OrientationAlignmentMode.OneAttachment
gyro.RigidityEnabled = true
gyro.Attachment0 = attach
gyro.Parent = root
local boostRemote = game.ReplicatedStorage.LedgehopRE
local maxDelay = 0.4
local t1 = 0
local hotfix = false
local animationUp = script:WaitForChild("Up")
local result
local XAxis = {
0; --Left
0 --Right
}
local YAxis = {
0; --Up
0 --Down
}
--// Just here so the code in the step doesn't look spaghetti as hell lol
function down(KEY)
return uis:IsKeyDown(Enum.KeyCode[KEY])
end
--// WHY THE HELL DOESNT CHANGED SIGNAL RETURN THE VALUE????
hum:GetAttributeChangedSignal("ClimbState"):Connect(function()
if hum:GetAttribute("ClimbState") == true then
local origin = root.Position
local direction = root.CFrame.LookVector
result = workspace:Raycast(origin, direction, params)
if result then -- where climbing starts
hum.AutoRotate=false
hum.PlatformStand=true
gyro.CFrame = CFrame.lookAt(result.Position+(result.Normal/2), result.Position)
move.Enabled=true
gyro.Enabled=true
else
hum:SetAttribute("ClimbState", false)
end
else
hum.AutoRotate=true
hum.PlatformStand=false
move.Enabled=false
gyro.Enabled=false
result=nil
end
end)
hum:GetAttributeChangedSignal("ClimbSpeed"):Connect(function()
spd = hum:GetAttribute("ClimbSpeed")
end)
--// Befored... I used a heartbeat:Wait() in a repeat until loop...
--// WELL THAT IS FIXED NOW!!
run.Heartbeat:Connect(function()
if hum:GetAttribute("ClimbState") == true and result ~= nil then
--// You may call me lazy and stupid but honestly how else would you do "Ledge Climbing"
--// Oh yeah also added the fact u just stop climbing if u climb down a lil too much
if root.Position.Y >= result.Instance.Position.Y + result.Instance.Size.Y/2 or root.Position.Y <= 2 then
hum:SetAttribute("ClimbState", false) --// gotta be here before we update the cframe.
--root.CFrame += root.CFrame.LookVector+root.CFrame.UpVector*2 -- og teleport
boostRemote:FireServer()
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
end
--// Secondary Ray for turning, could be edited to be all sides of a basepart! figure it out yourself.
--// No need for a if statement.
-- ledge turning
local sideOrigin = root.CFrame * CFrame.new(-.01, -0.3, -1).Position
local sideDirection1 = root.CFrame.RightVector*(down("D") and -2 or 2) --this is for end corners, opposite signs of 2 is for inside corners
local sideDirection2 = root.CFrame.RightVector*(down("A") and -2 or 2)
local hit = workspace:Raycast(sideOrigin, sideDirection1, params)
local corner = workspace:Raycast(sideOrigin,sideDirection2,params)
if corner and (down("D") or down("A")) then
if hotfix == true then return end
hotfix = true
if corner.Instance and corner.Instance ~= result.Instance then
print("not the same")
result = corner
gyro.CFrame = CFrame.lookAt(corner.Position+(corner.Normal/2), corner.Position)
root.CFrame = CFrame.lookAt(corner.Position+(corner.Normal/2), corner.Position)
wait(0.1)
hotfix = false
end
end
if hit and (down("D") or down("A")) then
if hotfix == true then return end
hotfix = true
if hit.Instance and hit.Instance == result.Instance then
print("the same")
gyro.CFrame = CFrame.lookAt(hit.Position+(hit.Normal/2), hit.Position)
root.CFrame = CFrame.lookAt(hit.Position+(hit.Normal/2), hit.Position)
wait(0.1)
hotfix = false
end
end
end
end)
--side = workspace:Raycast(char["Torso"].Position,Vector3.new(2,0,0), params)
--// I only did this because it looks cleaner.
do
local inputTask = {
[Enum.KeyCode.W] = function(state: boolean)
YAxis[1] = (state and 1) or 0
end;
[Enum.KeyCode.S] = function(state: boolean)
YAxis[2] = (state and 1) or 0
end;
[Enum.KeyCode.A] = function(state: boolean)
XAxis[1] = (state and 1) or 0
end;
[Enum.KeyCode.D] = function(state: boolean)
XAxis[2] = (state and 1) or 0
end;
[Enum.KeyCode.Space] = function(state: boolean)
if tick() - t1 <= maxDelay then
if state then
if hum:GetAttribute("ClimbState") == false then
hum:SetAttribute("ClimbState", true)
else
hum:SetAttribute("ClimbState", false)
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
end
end
else
t1 = tick()
end
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
--// LOL IDK BUT I THINK ITS CHARACTER CUS WE ARE MESSING WITH THE CHARACTER
run:BindToRenderStep("constraints update", Enum.RenderPriority.Character.Value, function()
if hum:GetAttribute("ClimbState") == true then
local X = XAxis[2]-XAxis[1]
local Y = YAxis[1]-YAxis[2]
move.VectorVelocity = Vector3.new(X*spd, Y*spd, 0)
end
end)
uis.InputBegan:Connect(function()
if hum:GetAttribute("ClimbState") == true then
local animationUp = script:WaitForChild("Up")
local Up = hum.Animator:LoadAnimation(animationUp)
local animationDown = script:WaitForChild("Down")
local Down = hum.Animator:LoadAnimation(animationDown)
local animationRight = script:WaitForChild("Right")
local Right = hum.Animator:LoadAnimation(animationRight)
local animationLeft = script:WaitForChild("Left")
local Left = hum.Animator:LoadAnimation(animationLeft)
local WDown = uis:IsKeyDown(Enum.KeyCode.W)
local SDown = uis:IsKeyDown(Enum.KeyCode.S)
local DDown = uis:IsKeyDown(Enum.KeyCode.D)
local ADown = uis:IsKeyDown(Enum.KeyCode.A)
if WDown then
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
Up:Play()
end
if SDown then
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
Down:Play()
end
if DDown then
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
Right:Play()
end
if ADown then
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
Left:Play()
end
end
end)
uis.InputEnded:Connect(function()
if hum:GetAttribute("ClimbState") == true then
local animationIdle = script:WaitForChild("Idle")
local Idle = hum.Animator:LoadAnimation(animationIdle)
for i,v in pairs(plr.Character.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
Idle:Play()
end
end)
I am wondering if it is a simple fix i am missing, or if it is a little more complex. If you need more info on the problem i can create a new starting place with the code for you to test yourself. Thank you. (also sorry if some stuff is formatted wrong, as this is one of my first posts)
i might be a bit late, but try changing your variables to this:
local sideOrigin = humanoidRootPart.Position + humanoidRootPart.CFrame.LookVector
local sideDirection1 = (isKeyDown("D") and -humanoidRootPart.CFrame.RightVector) or humanoidRootPart.CFrame.RightVector
local sideDirection2 = humanoidRootPart.CFrame.RightVector * (isKeyDown("A") and -2 or 2)
local hit = workspace:Raycast(sideOrigin, sideDirection1, raycastParams)
local corner = workspace:Raycast(sideOrigin, sideDirection2, raycastParams)
Hello, this is my main account, as I posted my problem on my friend’s account because I wasn’t able to comment yet. The climb script i used somehow broke while it was in disuse. I have tried my best to fix my issue, and also tried your solution, but to no avail. Thank you for your help, but I have made my own, somewhat similar system that is a little simpler, and will not be needing this system anymore.