Grappling hook causes players to glitch through parts

I made a simple grappling hook that barely works. The way I create grapples right now is setting them to the closest edge, either left, right, top or bottom of the part.

function Grapple:createGrapplingHook(position)
	grappling = true

	self.rope = Instance.new("RopeConstraint")
	self.rope.Visible = true
	self.rope.Color = BrickColor.new("Bright green")
	self.rope.Thickness = 0.2

	local attachment1 = Instance.new("Attachment", player.Character.HumanoidRootPart)
	local attachment2 = Instance.new("Attachment", workspace.Terrain)
	attachment2.WorldPosition = position

	self.rope.Attachment0 = attachment1
	self.rope.Attachment1 = attachment2
	self.rope.Length = (player.Character.HumanoidRootPart.Position - position).Magnitude
	self.rope.Parent = workspace

	-- Velocity for swinging
	local bodyVelocity = Instance.new("BodyVelocity")
	bodyVelocity.Velocity = Vector3.new(0, (position - player.Character.HumanoidRootPart.Position).Y, (position - player.Character.HumanoidRootPart.Position).Z).unit * swingForceMultiplier
	bodyVelocity.MaxForce = Vector3.new(0, swingForceMultiplier, swingForceMultiplier)
	bodyVelocity.Parent = player.Character.HumanoidRootPart

	-- Shorten the rope over time
	self.runServiceConnection = game:GetService("RunService").Heartbeat:Connect(function()
		if grappling then
			if enableShortening then
				local newLength = self.rope.Length - shortenSpeed
				self.rope.Length = math.max(0, newLength)
				if newLength > 3 then
					player.Character.HumanoidRootPart.CFrame = CFrame.new(player.Character.HumanoidRootPart.Position:Lerp(position, shortenSpeed / newLength))
				else
					grappling = false
					self.rope:Destroy()
					bodyVelocity:Destroy()
					self.runServiceConnection:Disconnect()
				end
			end
		end
	end)
	
	-- stop the raycast when the player releases the mouse button
	mouse.Button1Up:Connect(function()
		if grappling then
			grappling = false
			if self.runServiceConnection then
				self.runServiceConnection:Disconnect()
			end
			self.rope:Destroy()
			bodyVelocity:Destroy()
		end
	end)
end

My problem is that if the player is below the part and they click so the grapple is on top of the part then the player simply glitches through the entire part. How do I prevent this?

Firstly, I recommend using delta time so the shortening of the rope is always consistent.
Second, to solve your problem you can raycast between the Root Part and the Rope’s Goal

Place this above the if statement

local rp = RaycastParams.new()
rp.RespectCanCollide = true
rp.FilterDescendantsInstances = {player.Character}

local raycast = game:GetService("Workspace"):Raycast(attachment1.WorldPosition, attachment1.WorldPosition - attachment2.WorldPosition, rp)

Then at the if statement change it to:
if newLength > 3 and raycast == nil then

Let me know if you need anymore help with this problem or if this isn’t the desired effect!

Is it possible to set the player’s velocity to 0 when they hit the intersecting obstacle, instead of removing the grapple?

Sure, but I would like to make sure you understand the clipping is caused by the rope.

if newLength > 3 then
 -- Ur code goes here
elseif raycast ~= nil then
 bodyVelocity.Velocity = Vector3.new()
else
 -- Ur other code goes here
end

Isn’t clipping caused by the player having velocity moving against an object and then eventually through it? What do you mean that the rope causes the clipping?

The rope forcefully sets the length between it and the player, basically, if player’s distance > rope.Length then move player into minimum range.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.