Why is my collision so weird?

Hi developers,

There’s a weird thing happening to me, for some reason, my collision is not good, like look at this:


It may look normal, but sometimes i get flinged on the other side of the map, and i want to know why is this happening

Maybe it’s because of the ledge grab that i have, here’s my script:

local CollectionService = game:GetService("CollectionService")
local plr = game.Players.LocalPlayer
local Character = plr.Character or plr.CharacterAdded:Wait()
local Root = Character:WaitForChild("HumanoidRootPart")
local Head = Character:WaitForChild("Head")
local Hum = Character:WaitForChild("Humanoid")
local CA = Hum:LoadAnimation(script:WaitForChild("ClimbAnim"))
local HA = Hum:LoadAnimation(script:WaitForChild("HoldAnim"))
local TouchGui = plr:WaitForChild("PlayerGui"):FindFirstChild("TouchGui")
local UIS = game:GetService("UserInputService")
local cd=false
ledgeavailable = true
holding = false

local gyro
local LVele
local partCF
local LedgeAtt
local cross
local num

while game:GetService("RunService").Heartbeat:Wait() do
	local r = Ray.new(Root.CFrame.p, Root.CFrame.LookVector * 2 + Vector3.new(0,1.5,0))
	local part,position,normal = workspace:FindPartOnRay(r,Character)
	if part and ledgeavailable and not holding --[[and CollectionService:HasTag(part,"Ledge")--]] then
		if part.Size.Y >= 1 then
			if Head.Position.Y >= (part.Position.Y + (part.Size.Y / 2)) - 1 and Head.Position.Y <= part.Position.Y + (part.Size.Y / 2) and Hum.FloorMaterial == Enum.Material.Air and Root.Velocity.Y <= 0 then
				holding = true HA:Play() ledgeavailable = false
				partCF = part.CFrame
				Hum.AutoRotate = false
				if holding and not Root:FindFirstChild("Ledge") then
					game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
					game:GetService("Players").LocalPlayer.Character:FindFirstChildWhichIsA("Humanoid"):UnequipTools()
					local normalCFrame = part.CFrame:ToObjectSpace(CFrame.new(Vector3.new(0, 0, 0), -normal)) -- positive normal for reverse
					normalCFrame = normalCFrame - normalCFrame.Position
					local offsetCFrame = CFrame.new((part.CFrame:inverse() * Root.CFrame).Position)
					local newCFrame = part.CFrame * offsetCFrame * normalCFrame
					cross = Vector3.new(0, 1, 0):Cross(normal)

					gyro = Instance.new("BodyGyro")
					gyro.Name="Ledge"
					gyro.Parent = Root
					gyro.MaxTorque = Vector3.new(1,1,1) * 200000
					gyro.CFrame = newCFrame
					gyro.P = 20000
					LVele = Instance.new("BodyVelocity",Root)
					LVele.Name="LedgeVel"
					Root.Anchored = false
					LVele.MaxForce = Vector3.new(1,1,1) * math.huge
					LVele.Velocity = Vector3.new(0,0,0)
				end
			end
		end
	end
	
	function climb()
		if LVele then
			LVele:Destroy()
		end
		if gyro then
			gyro:Destroy()
		end
		local Vele = Instance.new("BodyVelocity",Root)
		Root.Anchored = false
		Vele.MaxForce = Vector3.new(1,1,1) * math.huge
		Vele.Velocity = Root.CFrame.LookVector * 10 + Vector3.new(0,30,0)
		HA:Stop() CA:Play()
		game.Debris:AddItem(Vele,.15)
		holding = false
		wait(0.2)
		game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, true)
		ledgeavailable = true
		Hum.AutoRotate=true
	end
	
	UIS.InputBegan:Connect(function(Key,Chat)
		if not holding then return end 
		
		if Key.KeyCode == Enum.KeyCode.Space and not Chat then
			climb()
		end
		
	end)
	
	if TouchGui then
		TouchGui:WaitForChild("TouchControlFrame"):WaitForChild("JumpButton").MouseButton1Click:Connect(function()
			if not holding then return end climb()
		end)
	end
end
2 Likes

Here is your code with some minor tweaks and debug logging. Recreate the issue and narrow down the issue using this:

local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UIS = game:GetService("UserInputService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local root = character:WaitForChild("HumanoidRootPart")
local head = character:WaitForChild("Head")
local humanoid = character:WaitForChild("Humanoid")
local climbAnim = humanoid:LoadAnimation(script:WaitForChild("ClimbAnim"))
local holdAnim = humanoid:LoadAnimation(script:WaitForChild("HoldAnim"))
local touchGui = player:WaitForChild("PlayerGui"):FindFirstChild("TouchGui")

local ledgeAvailable = true
local holding = false
local gyro, velocity

-- Logging function
local function log(message)
    print("[Climbing System] " .. message)
end

-- Function to handle climbing action
local function climb()
    log("Climbing initiated")

    if velocity then
        velocity:Destroy()
        log("Destroyed existing velocity")
    end
    if gyro then
        gyro:Destroy()
        log("Destroyed existing gyro")
    end
    
    local climbVelocity = Instance.new("BodyVelocity", root)
    climbVelocity.MaxForce = Vector3.new(1, 1, 1) * math.huge
    climbVelocity.Velocity = root.CFrame.LookVector * 10 + Vector3.new(0, 30, 0)
    game.Debris:AddItem(climbVelocity, 0.15)
    log("Created new climb velocity with value: " .. tostring(climbVelocity.Velocity))

    holdAnim:Stop()
    climbAnim:Play()
    holding = false
    wait(0.2)

    humanoid.AutoRotate = true
    ledgeAvailable = true
    game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, true)
    log("Climbing action completed")
end

-- Function to handle input for climbing
local function onInputBegan(input, gameProcessedEvent)
    if holding and input.KeyCode == Enum.KeyCode.Space and not gameProcessedEvent then
        log("Space key pressed, starting climb")
        climb()
    end
end

-- Function to handle touch GUI input for climbing
local function onJumpButtonClicked()
    if holding then
        log("Jump button clicked, starting climb")
        climb()
    end
end

-- Connect climb function to input
UIS.InputBegan:Connect(onInputBegan)

if touchGui then
    touchGui:WaitForChild("TouchControlFrame"):WaitForChild("JumpButton").MouseButton1Click:Connect(onJumpButtonClicked)
end

-- Main loop to detect ledges and handle holding state
RunService.Heartbeat:Connect(function()
    if not ledgeAvailable or holding then return end

    local ray = Ray.new(root.CFrame.p, root.CFrame.LookVector * 2 + Vector3.new(0, 1.5, 0))
    local part, position, normal = workspace:FindPartOnRay(ray, character)

    if part and part.Size.Y >= 1 then
        log("Detected part: " .. part.Name .. " at position: " .. tostring(position) .. " with normal: " .. tostring(normal))
        local partTopY = part.Position.Y + (part.Size.Y / 2)
        local headY = head.Position.Y
        
        log("Head position Y: " .. headY .. ", Part top Y: " .. partTopY)

        if headY >= partTopY - 1 and headY <= partTopY and humanoid.FloorMaterial == Enum.Material.Air and root.Velocity.Y <= 0 then
            log("Ledge detected, entering holding state")
            holding = true
            ledgeAvailable = false
            humanoid.AutoRotate = false
            holdAnim:Play()

            -- Disable backpack and unequip tools
            game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
            player.Character:FindFirstChildWhichIsA("Humanoid"):UnequipTools()
            log("Backpack disabled and tools unequipped")

            -- Calculate new CFrame for the root
            local normalCFrame = part.CFrame:ToObjectSpace(CFrame.new(Vector3.new(0, 0, 0), -normal))
            local offsetCFrame = CFrame.new((part.CFrame:inverse() * root.CFrame).Position)
            local newCFrame = part.CFrame * offsetCFrame * normalCFrame
            log("New CFrame calculated for holding position: " .. tostring(newCFrame))

            -- Set up gyro and velocity for holding position
            gyro = Instance.new("BodyGyro")
            gyro.Name = "Ledge"
            gyro.Parent = root
            gyro.MaxTorque = Vector3.new(1, 1, 1) * 200000
            gyro.CFrame = newCFrame
            gyro.P = 20000
            log("Gyro set up for holding position with CFrame: " .. tostring(gyro.CFrame))

            velocity = Instance.new("BodyVelocity", root)
            velocity.Name = "LedgeVel"
            velocity.MaxForce = Vector3.new(1, 1, 1) * math.huge
            velocity.Velocity = Vector3.new(0, 0, 0)
            log("Velocity set up for holding position with value: " .. tostring(velocity.Velocity))
        end
    end
end)

1 Like

Sorry for the late response, but i’m gonna try it later