Best way to do accurate hit detection with CFramed projectiles?

This isn’t entirely related to scripting, but I wasn’t sure where else to put this…

We’ve been using GetTouchingParts() every frame to detect collisions for larger parts. Since they’re large, one ray won’t suffice and multiple rays gets expensive and unreliable.

GetTouchingParts though also has a pretty big performance hit used like this. So we attempted using .Touched. As in, leaving the projectile unanchored and CFraming it regularly and then trying to “weld” a collision clone to the moving part via constraints. While the constraints work for slow projectiles, for faster projectiles, they spazz out and break. We’ve tried AlignPosition with RigidityEnabled, Ballsocket, Rod, Rope, you name it. They all don’t seem to work properly when the speed goes up.

Do you guys have any other ideas?

4 Likes

We could suggest Roblox adds box casting or sphere casting! (Unity has this)

One way you might be able to get away with this is to raycast from different points of the projectile. Considering the short distance of the rays, I bet it will have less performance issues than you might think.

16 Likes

RotateableRegion3 module is a thing, and available in Toolbox

But that’s not the same as casting

7 Likes

I’d imagine doing FindPartsInRegion3 every frame wouldn’t be that performance friendly either

Perhaps I’m wrong though

What I did for the projectiles in my game is send out the projectile to follow ray segments and detect whether the projectile collides with anything while following that ray (using the FindPartOnRay method), and if not then continue to the next ray segment; with there being a limit to how many ray segments can be created of coarse. Seems to have worked reliably, and no performance issues that I have noticed.

I have simplified the system above to give a generalization. There is a few other algorithms I had to apply to make things work optimally; those algorithms were fairly easy to create though.

1 Like

I don’t want to be rude but why are you CFraming projectiles in the first place? Often Roblox’s physics engine and body movers are incredibly capable. If they’re laggy I’ve found that almost always due to the projectile not having its network owner set properly.

You can do more and have a lot more precision when you CFrame projectiles. You can also handle the replication yourself and create a very efficient weapon system. On top of that, physical projectiles are bordering on archaic at this point, and using the Touched event has proven time and again to be not reliable enough. As you say, maybe that won’t be the case with network ownership set correctly (something you couldn’t do in years past), but it’s still an older way of doing things.

7 Likes

This

2 Likes

How many rays are you casting? Unless you’re doing thousands per second it’s unlikely to have any affect on performance :slightly_smiling_face:

4 Likes

More information on this please; When you say “You can handle the replication yourself” do you mean Remote:FireAllClients (or nearby clients) to create a mock projectile on their end? I’m trying to make a very efficient weapon system.

I’m not the person to ask if you are dealing with network stuff, however you are correct in assuming what I meant. You can replicated it to only the people that need it, control whether the server even see it, etc.

This isn’t my ideology and I won’t even take a stance either way, but some have been very obstinate that it is more efficient to not even have a physical representation of the bullet on the server, just send the position to the clients and have them replicate it. Network optimization is not my strong suit - if anything even is my strong suit now that I’m out of practice - but you could consider asking other people.

I wouldn’t blame him if he wouldn’t take the time to help with this seeing how busy life can be, but I have personally always looked up to AxisAngle, and he has even helped me with a few things in the past. But give it a search first. I’m sure there are guides and explanations that have been well critiqued and revised in the comments.

1 Like

If I could add onto what @JarodOfOrbiter is saying, bullet collisions only need to be handled on the server when they could hit a player. The pretty effects of flying bullets and bullet holes can all be handled by the clients who shot those bullets and replicated to the other clients.

The server only needs to step in for security when critical game features like health points are at stake (in other words for hit verification). Attacking clients can also actually perform the check to see if the server needs to get involved. If the attacking client wants the server to cause damage then it must ask the server to validate the shot. This shot validation can also tell the server which players it is likely to hit making collision detection even faster on the server by using a very small whitelist. Here is what a simple check may look like on the attacking client / server:

local maxDist = 2
local function isClose(playerPos, bulletRay)
    return bulletRay:Distance(playerPos) < maxDist
end

bulletRay is the unit direction bullet path before effects like bullet drop. Since this check uses C++ to calculate the distance it is likely to perform much better than an implementation in Lua. Each client should be able to perform tens of thousands of these a second without any lag.

I still maintain my position has stated in previous posts: damage and hit verification should only be performed on the server without trusting client information like how long ago the shot was or what their local game state was at the time of the shot. Trusting potential players that may be hit is fine because it is in the attacker’s advantage to tell the server (behave properly) and disadvantage not to tell the server (misbehave).

This method for reducing lag will work regardless of the actual method used to detect hits.

2 Likes

This module is good

1 Like