Hi, i’m trying to achieve an NPC that will be capable of finding players and killing them when in a specific magnitude. Despite this, I don’t particularly know how I should be going about when creating this with optimization in mind.
I’ve planned to use collectionservice for all the NPC’s and have one masterscript that controls all the NPC’s.
Here is my pseudo code that i’ve planned out but need help on:
-Collect all NPC’s
-Call function per NPC (ex: (GatherDistances(NPC)
-Repeat through player characters and when one is near, find a constant path to that player whilst not breaking the loop that checks for nearest players for the sake of target change
-If distance is close enough, then deal x damage
-If dead then end loop
Here is my problem: i’m not sure whether or not constantly checking for nearest players until the player dies per x interval is efficient and optimized. I’m also not sure how to handle the ability of changing targets when finding a new near player.
Here is an example: (Keep in mind that this uses collectionservice and will only be in one script)
repeat wait(x) --x could be wait() or 0.1
for _, root in pairs(rootparttable) do
--if root is close
--find path and walk there
end
end
until (NPC.Humanoid.Health == 0)
Remember, i’m not looking for how to make them. I’m more of asking on how it works. I’m attempting to find the most optimized layout of the code that will be able to work with a few dozen NPC’s with maybe a few players.
Any help will be greatly appreciated.
The way my swordfighting AI’s work, there are two relevant scripts per NPC, that being a FindPlayer script and a Move script:
FindPlayer looks for any living player that is within a closed distance of the NPC, usually 50 studs. Since players cannot close a 50-stud distance in, say one second, player distances are only updated once per second to see if they are within that 50-stud distance.
If at least one living player is found, FindPlayer assigns the nearest player to an InstanceValue, and if not, the InstanceValue's value is assigned nil.
What Move does is serve as an interface for a Moving AI retrieved from a ModuleScript that stores them. It also connects a function to InstanceValue.Changed:
If the player exists and is not the same player as before, enable the Moving AI.
and if the player does not exist, disable the Moving AI and return the NPC back to its initial position.
Any properties I want to contain are placed in Value instances parented to the relevant modules.
Your idea of making FindPlayer a singleton is a good one, and I might have to do that in my game when I get the time!
These two scripts are replicated to each NPC as a folder of ModuleScripts parented to a Replicator script in ServerScriptService, which also requires them once they are cloned and parented. This is also how I implement multiple AI’s, by parenting them all to the replicator script and letting that script deal with it. The replicator uses CollectionService to find every NPC by the way.
In my opinion, having one script that dictates player distances only would not be too bad, but placing all the different kinds of AIs and properties in the script as well would be breaking the single responsibility principle.
Therefore, I would modularize all functions and tasks into separate folders of or instances of ModuleScripts that are replicated and required by the distance script, and all relevant, static properties of the tasks into Value instances.
Yeah, using modulescripts would make the code cleaner. also, for future reference, you should pulblish code reviews in, well code reviews. Other than that, pretty good.