I created this Wall Climb System however it lags when switching surfaces. I have tried fixing it but no luck. It is detecting the wall just fine but when switching surfaces it teleports a bit to the left or right than back.
https://gyazo.com/b1000c78b33bfad77944e3d780b3bd2f
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local hittingWall = false
local onWall = false
local currentFace = nil
local climbVelocity = Instance.new("BodyVelocity")
climbVelocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
climbVelocity.Velocity = Vector3.new()
climbVelocity.P = 4000
local climbGyro = Instance.new("BodyGyro")
climbGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
climbGyro.CFrame = CFrame.new()
climbGyro.P = 4000
local climbParams = RaycastParams.new()
climbParams.FilterType = Enum.RaycastFilterType.Blacklist
climbParams.IgnoreWater = true
climbParams.FilterDescendantsInstances = {Character}
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Controls = {Up = 0, Down = 0, Left = 0, Right = 0}
local leftCast = false
local rightCast = false
function isKeyDown(Key)
return UserInputService:IsKeyDown(Enum.KeyCode[Key])
end
local Speed = 8
function Climb()
if hittingWall then
HumanoidRootPart.Velocity = Vector3.new(0,0,0)
if onWall then
climbVelocity.Velocity = HumanoidRootPart.CFrame.LookVector * 0 + Vector3.new(0,8,0)
end
end
end
function climbOff()
climbVelocity.Parent = nil
climbGyro.Parent = nil
hittingWall = false
onWall = false
Humanoid.PlatformStand = false
Humanoid.AutoRotate = true
currentFace = nil
end
UserInputService.InputBegan:Connect(function(input, GPE)
if input.KeyCode and not GPE then
if input.KeyCode == Enum.KeyCode.Z then
local rootOrigin = HumanoidRootPart.Position
local rootDirection = HumanoidRootPart.CFrame.LookVector
local rayResult = workspace:Raycast(rootOrigin, rootDirection, climbParams)
if rayResult then
currentFace = CFrame.new(rayResult.Position + rayResult.Normal, rayResult.Position)
HumanoidRootPart.CFrame = CFrame.new(HumanoidRootPart.CFrame.Position, Vector3.new(HumanoidRootPart.Position.X - rayResult.Normal.X, HumanoidRootPart.Position.Y, HumanoidRootPart.Position.Z - rayResult.Normal.Z))
climbGyro.CFrame = currentFace or CFrame.new()
climbVelocity.Parent = HumanoidRootPart
climbGyro.Parent = HumanoidRootPart
Humanoid.AutoRotate = false
Humanoid.PlatformStand = true
hittingWall = true
onWall = true
repeat
RunService.RenderStepped:Wait()
climbGyro.CFrame = currentFace or CFrame.new()
--currentFace = CFrame.new(rayResult.Position + rayResult.Normal, rayResult.Position)
if HumanoidRootPart.Position.Y >= ((rayResult.Instance.Position.Y + (rayResult.Instance.Size.Y / 2) ) + 3) and Humanoid.FloorMaterial == Enum.Material.Air then
climbOff()
end
local Movement = HumanoidRootPart.CFrame:VectorToWorldSpace(Vector3.new(Controls.Left + Controls.Right, Controls.Up + Controls.Down, 0)) * Speed
climbVelocity.Velocity = Movement
local sideOriginRight = HumanoidRootPart.CFrame * CFrame.new(0, 0, -4).Position
local sideDirectionRight = HumanoidRootPart.CFrame.RightVector * -4
local sideResultRight = workspace:Raycast(sideOriginRight, sideDirectionRight, climbParams)
if sideResultRight and (isKeyDown("D")) and not rightCast then
rightCast = true
print(sideResultRight.Normal)
HumanoidRootPart.CFrame = CFrame.new(sideResultRight.Position + sideResultRight.Normal, sideResultRight.Position)
--TweenService:Create(HumanoidRootPart, TweenInfo.new(0.3), {CFrame = CFrame.new(HumanoidRootPart.CFrame.Position, Vector3.new(HumanoidRootPart.Position.X - sideResultRight.Normal.X, HumanoidRootPart.Position.Y, HumanoidRootPart.Position.Z - sideResultRight.Normal.Z))}):Play()
currentFace = CFrame.new(sideResultRight.Position + sideResultRight.Normal, sideResultRight.Position)
--wait(0.1)
rightCast = false
end
local sideOriginLeft = HumanoidRootPart.CFrame * CFrame.new(0, 0, -4).Position
local sideDirectionLeft = HumanoidRootPart.CFrame.RightVector * 4
local sideResultLeft = workspace:Raycast(sideOriginLeft, sideDirectionLeft, climbParams)
if sideResultLeft and (isKeyDown("A")) and not leftCast then
leftCast = true
print(sideResultLeft.Normal)
HumanoidRootPart.CFrame = CFrame.new(sideResultLeft.Position+sideResultLeft.Normal, sideResultLeft.Position)
--TweenService:Create(HumanoidRootPart, TweenInfo.new(0.4), {CFrame = CFrame.new(HumanoidRootPart.CFrame.Position, Vector3.new(HumanoidRootPart.Position.X - sideResultLeft.Normal.X, HumanoidRootPart.Position.Y, HumanoidRootPart.Position.Z - sideResultLeft.Normal.Z))}):Play()
currentFace = CFrame.new(sideResultLeft.Position + sideResultLeft.Normal, sideResultLeft.Position)
--wait(0.1)
leftCast = false
end
until hittingWall == false
end
end
end
end)
UserInputService.InputBegan:Connect(function(input, GPE)
if input.KeyCode and not GPE then
if input.KeyCode == Enum.KeyCode.W then
if onWall then
Controls.Up = 1
end
elseif input.KeyCode == Enum.KeyCode.S then
if onWall then
Controls.Down = -1
end
elseif input.KeyCode == Enum.KeyCode.D then
if onWall then
Controls.Right = 1
end
elseif input.KeyCode == Enum.KeyCode.A then
if onWall then
Controls.Left = -1
end
end
end
end)
UserInputService.InputEnded:Connect(function(input, GPE)
if input.KeyCode and not GPE then
if input.KeyCode == Enum.KeyCode.W then
if onWall then
Controls.Up = 0
end
elseif input.KeyCode == Enum.KeyCode.S then
if onWall then
Controls.Down = 0
end
elseif input.KeyCode == Enum.KeyCode.D then
if onWall then
Controls.Right = 0
end
elseif input.KeyCode == Enum.KeyCode.A then
if onWall then
Controls.Left = 0
end
elseif input.KeyCode == Enum.KeyCode.Space and hittingWall then
climbOff()
end
end
end)