I’ve ran into a massive performance problem in Redshift Arena, my arena FPS that has been featured twice so far. Currently, for Custom-Explosion logic, I’m using GetDescendants on the workspace, which is actually not working out too well on the more detailed maps in my game. I’m wondering if using Region3 would be much better for something like this, or if there’s a better way to handle explosions. I was considering using Raycast, however, I’m not sure how to do a RayCast in a ball shape, so Region3 is my next best bet.
However, if someone can point me in the direction of using raycast for this instead, please let me know! Thanks!
I’d recommend looping through all characters caught within a (larger) Region3 and raycasting towards them only a certain distance. If the raycast hits them, then deal damage or kill them.
Good idea using a Region3 because looping through the workspace is VERY expensive if you have a lot of parts. Region3s break it up into chunks and check those, with which you can then just loop through to see what should actually hit.
How would the raycasts not hit the players if a wall or something similar is blocking the explosion? I like your idea of using Raycast, instead of doing a 360-degree ball.
That’s the nature of raycasts - they detect if something is in the way of the ray.
If you have the list of parts which are in the region, you can loop through them and see if they get hit by rays from the centre of the explosion.
You can use workspace:FindPartOnRayWithWhitelist to whitelist players.
On topic of whitelisting. Why not tag all players using collectionservice and then when an explosion accrues, get all tagged players and use rays rotated to the humanoidrootpart of the character and set a ray size (the explosion radius) so not everyone gets hit. Then just use workspace:FindPartOnRayWithWhitelist to check if the ray hit the player or not.
If all you’re trying to achieve with the custom explosions is damaging players, this is a good way to go about it:
For loop through all the players in the game, get the position of their character’s HumanoidRootPart
Compare the distance between your explosion’s center and their HumanoidRootPart’s position
Check if the distance is within the ‘radius’ of the explosion, proceed only if this is true
Cast a ray from the explosion center to the character’s position, if this ray collides with a part inside the Character, we deal damage
I personally implement this method for explosions in all my games and have not had any performance issues with it, and I believe it’s far less expensive compared to using a Region3.
I’m pretty sure you can simply just create an explosion normally, but just set the Visible property to false. Then, you can use the .Hit event to detect any hit parts within the explosion radius. To make the explosion completely harmless and not push parts, set the .BlastPressure to 0 and .DestroyJointRadiusPercent to 0.
Raycasts are better than region3 because what happens if the explosion happens behind a wall? The player dies anyways? Unless you want the wall to be destructible you would want to use raycast (plus raycast is pretty easy to implement for destructible walls).
Also:
Region3 makes a rectangle from two points
Raycast simply sends a ray in a direction (then stops at “magnitude” distances)
Region3 is only being used for (as the name states) regions. The Region3 determines the radius around the explosion and any parts within that Region are fetched. The raycasts are then sent out to parts within that region to take effect.
If you only use raycasts, then you’re going to end up iterating over an entire table of things regardless of their positioning. Region3 helps to minimise those results only to parts that are within the area.
That makes it much more efficient, but I thought Region3 was only a rectangle scan. You need two points, so unless I have it wrong I think it only makes a rectangle. Is there a function that makes a sphere scan?
Think of the WorkSpace:FindPartsInRegion3() call as a first pass at getting all the parts intersecting a sphere of diameter D centered at Vector3 P. First we create a cubic region centered at P with sides of length D, then we fire a ray from P to each part found within the region to determine: a) if the ray actually intersects the part we’re testing, and b) if the ray’s length is less than or equal to D/2. If the answer to both of these is yes, then the part is within the sphere of radius D/2 centered at P.
No. What I described is a way to use bothFindPartsInRegion3() and FindPartOnRay() to find parts that lie within a sphere. The Region3 is in fact a cube, we’re just using it to reduce the amount of computation
That would make sense, but wouldn’t it be simpler to just make a white list of all the parts that are “explodable” and then check if they are within a set amount of studs, then do the magic with raycasting? It would basically amount to the same amount of computation and would work maybe better than Region3, but that’s just me thinking out loud at this point…
That will work fine as long as the size of the whitelist is kept small, but as more and more parts are added most of our time is going to be spent doing magnitude calculations on parts that aren’t even close to being within our desired radius.