How to make part ricochet?

Hello! I want to know how to make a part ricochet but not run code the whole time. But just make it run when a touched event is fired. After that I will make the part rotate accordingly and update the body velocity to match. heres my current code thanks so much i know you are reading this right now so please help.

local function Shoot(hrp,mouseCF,spellName)

	local rng =

	local laser ="Part")
	laser.CFrame = hrp.CFrame
	laser.Parent = workspace
	local maxDistance = 200
	local curDistance = 0

	local stepDistance = 4
	local stepWait = 0

	local currentPos = hrp.Position
	local currentNormal = (mouseCF - hrp.Position).lookVector

	local function Step(overrideDistance)
		-- Cast ray:
		local params =
		local direction = currentNormal * (overrideDistance or stepDistance)
		params.FilterType = Enum.RaycastFilterType.Blacklist
		params.FilterDescendantsInstances = {hrp}
		local result = workspace:Raycast(currentPos, direction)
		local pos

		if result then
			pos = result.Position
			pos = currentPos + direction

		-- Update laser position:
		laser.Size =, 0.4, (pos - currentPos).Magnitude)
		laser.CFrame =, 0.5), pos)

		local oldPos = currentPos
		currentPos = pos

		if result then
			-- r = d - 2(d DOT n)n
			-- Reflect:
			local norm = result.Normal
			local reflect = (currentNormal - (2 * currentNormal:Dot(norm) * norm))
			currentNormal = reflect
			Step(stepDistance - (pos - oldPos).Magnitude)

		curDistance = (curDistance + (pos - oldPos).Magnitude)

		-- Apply fade effect to laser as it approaches max distance from < 75 studs:
		if curDistance > (maxDistance - 75) then
			local d = (curDistance - (maxDistance - 75)) / 75
			laser.Transparency = d

		-- Recurse if max distance not reached:
		if curDistance < maxDistance then


	-- Done! Destroy laser:


You can use CFrame.lookAt() to rotate the part towards a CFrame that you can easily create a few studs into the direction of your reflection normal and you could just set the BodyVelocity to the reflection normal.
I don’t really get what youre going for, you’re using racasting, but then when you hit something you want the part to be moved by physics in order to fall down, I’m guessing? You could just keep using raycasting and lower the CurrentNormal incrementially to simulate it dropping to the ground, assuming you want the falling part to be able to deal damage or hit someone. That would be better for performance than all the physics, especially when you have many of them firing at once

Hello! Thank you for replying, you are really talented with CFrames. What I actually want to do it to make that part ricochet. Which is basically make it bounce like this:
Here is the

script that uses body velocity
local fireball = game.ServerStorage.Spells:FindFirstChild(spellName):Clone()
local bodyVel ="BodyVelocity")
fireball.CFrame = hrp.CFrame
bodyVel.MaxForce =,9999999999999999,9999999999999999)
bodyVel.Velocity = (mouseCF - hrp.Position).lookVector * spellSpeed
bodyVel.Parent = fireball

Now I just need to know how to get the angle at which they hit the object so that I can update the fireball’s CFrame and bodyVelocity to make it bounce accordingly. Please help me just this bit more. Thanks!


What exactly do you mean by angle? The literal angle in radiants? I don’t get why you would need that, you already did the reflection math.


Yes. That was what I meant. But I’m a noob at raycasting no matter how much acticles I read I still don’t get it. But what I noticed was that the function Step() in my first script runs the entire time my fireball is in workspace. I want to make it only run when touched, make my fireball rotate, and then stop running until it gets touched again. But I’m not sure how to connect it to a touched event as it runs the whole time. Please help me out. Thanks you so much! I know that you can do it :slight_smile:

1 Like

have you seen this post?

nevermind, you are already using the code for it

Thanks but do you know how to make the code only run when it is touched and after the racasting and all that reflects the part, i want to code to stop running because it lags a lot. please help thanks you so much!