So basically I have an enemy for my RPG. I have been trying to cut down this code without it taking up too higher percentage on the script performance output. This is because usually i have an RPG with about 140 Enemies, and of course too many scripts causes roblox to lag.
function findNearestTorso(pos) -- Find the character local list = game.Workspace:GetChildren() local Torso local temp local Distance = 10 local humanoid local temp2 for x = 1, #list do temp2 = list[x] if (temp2.className == "Model") and (temp2 ~= script.Parent) then temp = temp2:findFirstChild("Torso") humanoid = temp2:findFirstChild("Humanoid") if temp and humanoid and humanoid.Health > 0 then if (temp.Position - pos).magnitude < Distance then Torso = temp Distance = (temp.Position - pos).magnitude else Humanoid:MoveTo(NPCSpawn.Position, NPCSpawn) end end end end return Torso end while Figure.Parent do -- figure being the humanoid in this guy wait(n) local Target = findNearestTorso(Torso.Position) -- player if Target then Humanoid:MoveTo(Target.Position, Target) TouchValue.Value = true n = 0.1 local amt = RunService.Stepped:wait() if amt > nextTime then -- make this guy walk correctly! move(amt) nextTime = amt + .01 else NPCSpawn.Touched:connect(function() -- The NPCSpawn is where the enemy spawns, when a player moves out of radius, the enemy will go back to spawn wait(0.2) script.Touching.Value = false n = 0.7 end) end end end
And of course this runs frequently to check whether there is a player. This animation script is very.. all over the place. i was wondering if there was an easier way of detecting a player, for example adding a big (transparent) block in the enemy, and when it is touched it shall chase the player. But Ive got some welding probs with that. Anyway, thanks for the help if you actually read all of this ha ~ thx bubs
Unfortunately, there is no easier way I can think of to find the closest Player other than to loop through all of the players. However, you are looping through everything parented to the workspace.
A better way to accomplish what you want is to limit how may times you loop. What we can use is the method of Players GetPlayers
in order to look at all the players in the game.
local function findNearestPlayer(pos) local closestPlayer = nil local distance = math.huge for _, player in next, game.Players:GetPlayers() do if player.Character then if (player.Torso.Position - pos).magnitude < distance then closestPlayer = player end end end return closestPlayer end
A potential improvement would be to use one script to operate all of the enemies. You can set up a loop that creates threads that runs the function used for each character.
Example code
local NPCs -- A list of all NPCs local NPCFunctions -- A list of all functions for different NPCs for _, npc in next, NPCs do local type -- determined type of NPC (could use a value object in the NPC itself) local NPCFunction = NPCFunctions[type] spawn(function NPCFunction() end) end
Example Table for NPCFunctions
local NPCFunctions = { ["Pirate"] = function() print("arhg!") end ["Cow"] = function() print("moo!") end }
One improvement for tidiness would be to put the NPCFunctions in a ModuleScript. You could also define the functions outside of the table to make that easier to read as well.
And if there is any code that is constant across all of the NPCs, you could put it into a function that receives arguments that may be specific to that NPC type (or even another function).
local function Pirate() print("arhg!") end local function ConstantCode(type, otherFunction) print("I am an NPC of type " .. type) otherFunction() end ConstantCode("Pirate", Pirate) --[[ Output : I am an NPC of type Pirate argh! ]]
Of course this is just one way I conceptualized accomplishing this, so you may find a better way to organize all the data, but making it so that all of these NPCs are controlled with one script will for sure help to improve performance.