Projectiles and workspace:FindPartOnRay()

I’m using FindPartOnRay for a projectile, and the ray is of course the same as the trajectory of the projectile, but how do I check when the projectile is touching the part from FindPartOnRay (if it’s not nil)? Do I just check the projectile’s position every heartbeat or instead take the unit-ray (of the trajectory) instead and then if there’s a part using FindPartOnRay that means it touched since it’s just one?

I’m gonna list some possible approaches from the top of my head, the choice is yours.

  • Use :GetTouchingParts() on the projectile every heartbeat (wouldn’t recommend)

  • Use the .Touched event on the projectile and check if the BasePart that the projectile hit is the same BasePart from :FindPartOnRay(). The variable passed through the .Touched event is the BasePart that the projectile hit, by the way.

That is a horrible idea. The projectile can just fly through a part in case of lag, meaning no collision for the gameplay.

If your projectile’s physics are scripted then:

local ignpart
local whlist = {ignpart}

local pos0 = Vector3.new()
local pos1 = Vector3.new()
local acc = Vector3.new(0,-9.81*2.5,0)

local con;con = game:GetService("RunService").Heartbeat:Connect(function(dt)
  pos1,pos0 = 2*pos1 - pos0 + acc * dt*dt, pos1

  local ray = Ray.new(pos0,pos1-pos0)
  if not workspace:FindPartOnRay(ray,ignpart) then
    local P,p,n = workspace:FindPartOnRayWithWhitelist(ray,whlist)
    if P then
      --stuff
    end
  end
end)

Otherwise, you could replace pos0 with the old position of the projectile part and pos1 with its current.

1 Like

Run it on the client to minimise that :stuck_out_tongue:

Still a horrible practice. Also, clients are more prone to unstable frame rate.

I’m using BodyVelocity so how do I know what the acceleration is?

Idk if there’s an inbuilt function, but:

Acceleration = Change in velocity / Change in time


  • Record the position of the projectile.
  • Record the position again, lets say after 0.25 seconds.
  • Work out the magnitude between the two vectors (Vector1 - Vector2).magnitude
  • Divide the magnitude by the time elapsed (0.25 seconds) to work out the acceleration (studs per second squared)

Then we are talking about the second mentioned case. You are moving the projectile with BodyMovers, not a function.

local ignlist = {ignpart,projectile}
local whlist = {ignpart}

local pos0 = projectile.Position

local con;con = game:GetService("RunService").Heartbeat:Connect(function(dt)
  if not projectile then con:Disconnect() return end
  local pos1 = projectile.Position

  local ray = Ray.new(pos0,pos1-pos0)
  if not workspace:FindPartOnRayWithIgnoreList(ray,ignlist) then
    local P,p,n = workspace:FindPartOnRayWithWhitelist(ray,whlist)
    if P then
      --stuff
    end
  end
  pos0 = pos1
end)