Hi! I’m creating a system where you can climb/vault over high walls (kinda like gta).
I have put together a system that works great the first time its run… however after the first climb it becomes very inconsistent and it almost always fails.
local script inside of startercharacterscripts
local player = game.Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local rootPart = character:WaitForChild("HumanoidRootPart")
local head = character:WaitForChild("Head")
local climbAnim = humanoid:LoadAnimation(script:WaitForChild("Climb"))
--vaulting
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local canVault = true
local ledgePart = nil
local UIS = game:GetService("UserInputService")
local pressed = 0
local function partCheck(ledge)
local vaultPartCheck = workspace:Raycast(ledge.Position + Vector3.new(0, -1, 0) + ledge.LookVector * 1, ledge.UpVector * 3, raycastParams)
if vaultPartCheck == nil then
return true
else
return false
end
end
local function detectLedge()
if (humanoid:GetState() == Enum.HumanoidStateType.Freefall or humanoid:GetState() == Enum.HumanoidStateType.Jumping) then
local vaultCheck = workspace:Raycast(rootPart.CFrame.Position, rootPart.CFrame.LookVector * 5, raycastParams)
if vaultCheck then
if vaultCheck.Instance then
local localPos = vaultCheck.Instance.CFrame:PointToObjectSpace(vaultCheck.Position)
local localLedgePos = Vector3.new(localPos.X, vaultCheck.Instance.Size.Y/2, localPos.Z)
local ledgePos = vaultCheck.Instance.CFrame:PointToWorldSpace(localLedgePos)
local ledgeOffset = CFrame.lookAt(ledgePos, ledgePos - vaultCheck.Normal)
local magnitude = (ledgePos - head.Position).Magnitude
if magnitude < 4 then
if partCheck(ledgeOffset) then
ledgePart = Instance.new("Part")
ledgePart.Parent = workspace
ledgePart.Anchored = true
ledgePart.Size = Vector3.one
ledgePart.CFrame = ledgeOffset + Vector3.new(0, -2, 0) + ledgeOffset.LookVector * -1
ledgePart.CanQuery = false
ledgePart.CanCollide = false
ledgePart.CanTouch = false
ledgePart.Transparency = 1
climbAnim:Play()
rootPart.Anchored = true
humanoid.AutoRotate = false -- so shift lock doesnt't rotate character
rootPart.CFrame = rootPart.CFrame:Lerp(CFrame.lookAt(ledgePart.Position, (ledgePart.CFrame * CFrame.new(0, 0, -1)).Position), .25)
climbAnim.Stopped:Wait()
rootPart.Anchored = false
character:MoveTo(Vector3.new(rootPart.Position.X, vaultCheck.Instance.Position.Y + vaultCheck.Instance.Size.Y*0.5 + 0.2, rootPart.Position.Z))
humanoid.AutoRotate = true
ledgePart:Destroy()
end
end
end
end
end
end
UIS.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Space then
if tick() - pressed < 0.2 and tick() - pressed > 0 then
detectLedge()
end
pressed = tick()
end
end)
first climb - Roblox Studio (gyazo.com)
second climb - Roblox Studio (gyazo.com)
I have also noticed that server sided the player is weirdly aligned to the middle of the ledge.
So far ive tried making the entire aligment and raycast serversided but that did nothing but make the system slower.
Any help is much appreciated!