For a project I am working on, I am working a lot with raycasts. Whenever I cast a ray, I need to ignore specific objects, but the rules for which object to ignore are a little tricky. In essence, there are different ignore lists per team. For each team, the ignore list exists out of:
- Characters of players in that team
- Objects tagged RAY_IGNORE (but there are some team-specific exceptions)
I have the logic working for the second part, which is objects that are tagged RAY_IGNORE. However, I am struggling with figuring out how I can best approach adding player characters to these ignore lists.
Rays will be cast very often (potentially tens of times per second), so recreating the ignore list whenever you cast a ray can become an expensive process real quick, which is why I figured I should have one array per team to which I add objects when needed. When an object tagged RAY_IGNORE gets destroyed, I keep them in the list because these arrays get refreshed at the end of a round anyway, and removing these parts could mean looping through an array of a couple hundred objects to find out which index I have to remove from the array. Keeping these removed parts around in memory temporarily does not significantly impact performance at all.
This approach does not work well for characters however. Before a round ends, characters could have respawned a hundred times. If I were to treat characters the same way as above, that means I could potentially have an array with references of a hundred dead characters (including textures, accessories, and more). These references do not get cleaned up until the end of the round and so I will be taking up a lot of memory towards the end of a round. However, I am not keen on removing characters from these arrays either whenever they die, because that means that in the heat of combat I might be looping through hundreds of objects every second.
My original solution to this problem was to not only have team-specific arrays in which I keep the RAY_IGNORE objects, but to also create a separate array for each team in which I store the character models. Whenever I cast a ray I combine the two arrays into a new array that I use as the final ignore list. However, a raycastβs ignore list does not support nested arrays, so I cannot do e.g.
function ReturnIgnoreList()
-- IgnoreParts and IgnoreCharacters are team-specific arrays
local IgnoreList = {IgnoreParts, IgnoreCharacters}
return IgnoreList
end
So I am now looking for a new approach. These are the approaches I am currently thinking of:
-
I keep a separate team-specific array for the character models and the RAY_IGNORE objects. When character models are removed I remove them from their array as well, which will be fast because the array is short. And whenever I cast a ray I create a new table into which I unpack the RAY_IGNORE array, and then add the character models to the end of this new array afterwards. However, this sounds like it would nullify most of the performance benefits that I was hoping to create in the first place.
-
Combine the player characters into the array with RAY_IGNORE parts, and whenever they die just keep the reference of the character models in those lists. This might take up significant memory though towards the end of a round, but will save computing power.
-
Combine the characters into the array with RAY_IGNORE parts, and whenever they die, loop through the whole table to find out which index holds the dead character and remove that index. This will take up less memory, but it will put a little more stress on the CPU.
I am hoping that there might be a more elegant solution that someone can share with me. If not, I hope that someone with more experience on this subject can help me figure out which of the given approaches I should take by explaining the benefits and downsides of each option.