Efficient Aggro Approaches

My first topic! I’m about to tackle NPC aggro and hostility for the first time.

  1. I’m going to create my own approach to aggro and need some advice regarding any built-in functionality Roblox offers.

  2. Every solution I’ve read suggests a script that would exist in every NPC humanoid and the script would contain a “while true” which constantly checks for a near torso. On finding a torso (meant to be the player) the path would be established to that player. I feel this is a demanding approach because the script would need to cycle through all other NPC humanoids until it finds a player.

  3. I’ve looked for solutions but they all suggest that NPC contain the script and I’d like to try an approach that involves the players character/humanoid aggroing the NPC even if it’s from a fair distance i.e. there is no line of site.

What functions and technology might I consider?

I would sort through the players, get the distance from their character, then move the NPC to the closest one.

local Npc = --Your npc  

while true do
for _, Player in pairs(game.Players:GetChildren()) do

local Distance = Player:DistanceFromCharacter(Npc.Torso.Position) --The distance from the player's character to the Npc's humanoid root part
if FarthestDistance == nil or Distance > FarthestDistance then
FarthestDistance = Distance

end
end

Npc:MoveTo(Player.Character.HumanoidRootPart.Position)
end
1 Like

If I understand that script correctly. You are suggesting that each NPC contains this script and so it would be running for 30-50 NPC at a time for example.

Is that correct?

Would it be a stupid approach to add a 100% transparent circle to players and use it to aggro NPC when that circle passes through them?

That was the first idea I ever had on this. It’s just strange to think that every player would have a massive circular part around them but it would create a radius.

This sounds like a bad idea, I assume you would be using Touched to detect aggro, which is far more intensive than a magnitude check.
You should be yielding somewhere inside the distance check loop (and mob decision making) so the mob doesn’t hog up server resources. I found yielding for around 100 ms (wait(0.1)) every loop works well. If you’re familiar with state machines, this is the clock period.

1 Like

It would actually be good to put all the npcs in a folder, and then have one script sort through all of them and move them all to the closest player. In this case, I put all of them in a folder named “Npcs.”

local Npcs = game.Workspace.Npcs:GetChildren()

for _, Npc in pairs(Npcs) do

while true do
for _, Player in pairs(game.Players:GetChildren()) do

local Distance = Player:DistanceFromCharacter(Npc.Torso.Position) --The distance from the player's character to the Npc's humanoid root part
if FarthestDistance == nil or Distance > FarthestDistance then
FarthestDistance = Distance

end
end

Npc:MoveTo(Player.Character.HumanoidRootPart.Position)
end

end

Instead of a circular part, you can merely check if a player is within a certain amount of studs from the npc. The DistanceFromCharacter(part) method returns the total amount of studs the character is from the part in the parentheses. (Might not be entirely correct, I’m a little shaky in this area.) so if you want your npcs to move to a player if they are within a certain amount of studs, this should work.

local Npcs = game.Workspace.Npcs:GetChildren() --Change this to your folder containing your Npcs
local AmountOfStuds = 10 - -The amount of studs a way a player a player will set off the npc.

for _, Npc in pairs(Npcs) do

while true do
for _, Player in pairs(game.Players:GetChildren()) do

local Distance = Player:DistanceFromCharacter(Npc.Torso.Position) --The distance from the player's character to the Npc's humanoid root part

if Distance < AmountOfStuds then
Npc:MoveTo(Player.Character.HumanoidRootPart)
end

end
end
2 Likes