What is a delay-free method to detect collisions on projectiles?

Hello. Currently, I am developing a third-person shooter game.
In my last thread, I got a nice introduction on moving projectiles. Cool. But, a projectile needs collision detection. I have heard, that using the touched event never should be used. So I tried these two things:

1. Use GetTouchingParts on Heartbeat
On Heartbeat, I always checked GetTouchingParts on the projectile.

2. Casting a ray every Heartbeat
Every Heartbeat, I casted a ray into the direction of the projectile’s lookVector and checked for the part on that.

Both of these methods worked fine, but had 1 problem:
It doesn’t recognize the collision instantly.
Look at this footage:


The bullet slides on the SpawnPoint for some time. As it might be something different on me, here’s my script:
function shootingSystem:Fire(gun, faceto)
    --Placing and facing the projectile
    local projectile = gun.Projectile:Clone()
    projectile.CFrame = CFrame.new(gun.Model.Main.Position, faceto)

    --Creating the BodyVelocity
    local velocity = Instance.new("BodyVelocity")
    velocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
    velocity.Velocity = projectile.CFrame.lookVector * gun.ProjectileSpeed
    --Parenting the velocity
    velocity.Parent = projectile

    --Checking if the projectile is touching anything every heartbeat
    local connection
    connection = RunService.Heartbeat:Connect(function()
        print("Heartbeat fired:".." "..tick())
        local touching = GetTouching(projectile)
        print("Got touching part: ".." "..tick())
        if(touching ~= nil) then
            --Something has been touched. Destroy the projectile and disconnect the event connection
            print("Touched something on "..tick().."!")
            connection:Disconnect()
            projectile:Destroy()
        end
    end)

    --Firing the projectile and removing it after it's lifetime
    projectile.Parent = workspace
    Debris:AddItem(projectile, gun.ProjectileLifetime)
end

Are there any other methods? Can I fix the ones I already tried? Is the touched event still unusable, or quite reliable nowadays? Thanks in advance - Sonnenroboter. :slight_smile:

1 Like

The best way to do it would be to have continuous ray casts every frame, and just position the part each frame on the the ray for the client. I’d suggest looking at the FastCast module or make your own. If you don’t need all the fancy physics for realistic projectile motion it should be pretty easy to just create one that travels straight in one direction.

This is a (looking good) way of creating a projectile, though that’s not quite an answer to my problem, unfortunately. I’ll make sure to check it out.

Fast Cast was the solution for my shooter projects for a long time, even if you don’t use the module it’s FULL of knowledge and information, by far the best way to handle projectile collision in my opinion is this, hope if helps you!

1 Like

Unfortunately, it did not as FastCast doesn’t use Body movers. :frowning:

1 Like

Could you possibly use a Region3 which is set just bigger than the projectile’s size and a tad bit higher than the projectile’s position.

Then you can use FindPartsInRegion3 (obviously having the projectile ignored) and check if there’s a part in the returned array.

You could cast the ray on the client and tell the server the results. The client can give the player instant hit feedback like this.

The server can then verify if what the client did was “right” before allowing the original client’s results to be replicated to other players.

This is how most FPS games have seemingly instant collision detection.

Not sure if this is any help, but this coding fixed my issue and I have since used it with other projectiles.

With fast moving projectiles that would be no problem. But with slower moving projectiles, the target could move and the shot could not hit anymore, right? What can be done against that? Also, when would the damage actually be dealt?

How fast are the projectiles in question? You could raycast immediately to see how far the target is, wait until you think the projectile is about to hit it, and then raycast again.

I would immediately show the damage on the client that shot the projectile but do nothing on the server until you’re certain it was an accurate hit.

I think projectile speeds will vary a lot. Some will be slow and some faster than the Naruto run.

I’ll try out your method now.