Why does raycast not detect my projectiles sometimes?

local BodyVelocity = Instance.new("BodyVelocity")
		BodyVelocity.MaxForce = Vector3.new(100000,100000,100000)
		BodyVelocity.Velocity = Object.PrimaryPart.CFrame.LookVector * Speed
		BodyVelocity.Parent = Object.PrimaryPart
		
		local HB
		HB = game:GetService("RunService").Heartbeat:Connect(function()
			if Object and Object.Parent then
				local Params = RaycastParams.new()
				Params.FilterType = Enum.RaycastFilterType.Blacklist
				Params.FilterDescendantsInstances = {workspace.VFX, Caster}
				local Cast = workspace:Raycast(Object.PrimaryPart.Position, Object.PrimaryPart.CFrame.LookVector * 1.5, Params)
				local hitPart
				if Cast and Cast.Instance then

This part right here is where I check if a parts been hit. But sometimes it doesn’t even get detected? Why is this?

Projectile travels too fast and the ray’s too short (only 1.5 studs)

I’ve seen projectiles that travel a lot faster though… And when the object hits the character it’s supposed to stick to them from where it hit. I can’t just increase the length, or it will look like the projectile didn’t hit them.

Projectile speed itself isn’t the problem, its your raycast being way too short. You could try dynamically changing the ray length based on the speed of the projectile

workspace:Raycast(Object.PrimaryPart.Position, Object.PrimaryPart.CFrame.LookVector * Object.PrimaryPart.AssemblyLinearVelocity.Magnitude, Params)

Also, consider aliasing objects in your code so that it’s easier to read and edit
Also #2, you shouldn’t be creating a new RBXScriptConnection binded to Heartbeat FOR EACH PROJECTILE, you can organize the hit registration system into a table and a loop
Also #3, you don’t need to create a new RaycastParams object every time the projectile raycasts, its super redundant when you can create just one at the top of the script and use it over and over again

I tried your idea, little problem though the projectile detects something from like 10000 meters away. What should I do about that?

#1 It’s a projectile script, so if I just named it ‘Fireball’ that would be weird since it’s for more than 1 object that needs to go flying in a direction.

#2 Yeah I probably shouldn’t use a Heartbeat each time, that would cause lag now that i’m thinking about it thanks for pointing that out.

#3 Uhh But if more vfx is parented into the vfx folder as the objects being fired there’s a chance that it won’t blacklist that since it’s only blacklisting the old table of vfx?

I forgot that velocity is measured in studs per second and you’re doing hitreg on a per frame basis; you will also need to grab the delta-time from Heartbeat to “normalize” the ray’s length

HB = game:GetService("RunService").Heartbeat:Connect(function(dt) --"dt" is deltatime
...
workspace:Raycast(Object.PrimaryPart.Position, Object.PrimaryPart.CFrame.LookVector * Object.PrimaryPart.AssemblyLinearVelocity.Magnitude * dt, Params)

#1 What I meant by aliasing is using local variables to shorten the reference call of objects. For example, instead of doing Object.PrimaryPart over and over again whenever you want to use it, you can alias it to a local variable and use that instead:

Object and Object.Parent then
    local prim = Object.PrimaryPart

#3 Whitelist/blacklist applies to all of the descendants of the instance in question. You don’t have to worry about new children being parented, they’re still whitelisted/blacklisted because their parents are

1 Like