How to prevent Monsters from attacking each other?

Hello! I’m programming a monster right now, however I have run in to a problem.
When there is more than one monster in the game, the monsters will attack each other instead of the player.
How do I make them only attack the player?

Script:

function findNearestPlayer(Position)
	wait(0.3)
	local List = game.Workspace:children()
	local Torso = nil
	local Distance = 30
	local Temp = nil
	local Human = nil
	local Temp2 = nil
	for x = 1, #List do
		Temp2 = List[x]
		if (Temp2.className == "Model") and (Temp2 ~= script.Parent) then
			Temp = Temp2:findFirstChild("HumanoidRootPart")
			Human = Temp2:findFirstChild("Humanoid")
			if (Temp ~= nil) and (Human ~= nil) and (Human.Health > 0) then
				if (Temp.Position - Position).magnitude < Distance then
					Torso = Temp
					Distance = (Temp.Position - Position).Magnitude
				end
			end
		end
	end
	return Torso
end

while true do
	local target = findNearestPlayer(script.Parent.HumanoidRootPart.Position)
	if target ~= nil then
		script.Parent.Humanoid:MoveTo(target.Position, target)
	end
end

Thanks :slight_smile:

Keep an up to date list of the players. Only attack from that list. :slight_smile:
Players:GetPlayers (roblox.com)

3 Likes

To expand on this, you will want to get the player’s character and check that it’s not nil. If the player is nil, they are not in the game. If the player’s character is nil, they may not be spawned yet, etc. So make sure to do those checks so your script doesn’t error.

1 Like

Firstly, findFirstChild() is deprecated, as is :children() too.

For the the help part, you should check if the character the script is looking at has a certain value to distinguish it from other players. Basically create a bool value in the monster for it to be easy to know if it is a player or not.

1 Like

Because I am still learning to script, would it be possible to get a code example for the purpose of learning?

Sure!

Players = game:GetService("Players")

function findNearestPlayer()
  for i, player in pairs(Players:GetPlayers()) do
      if player ~= nil then
        local character = player.Character
          if character then
            -- Do your distance and other checks, etc. here
          end
      end
  end
end
1 Like
-- It is recommended to keep services in the global scope repeatedly calling GetService might cost some performance.
local players = game:GetService("Players");

for _, player in ipairs(players:GetPlayers()) do
	-- Probably unnecessary
	if (not (player)) then
		continue;
	end

    -- Character is a property / pointer, meaning it won't error when trying to index.
	local character = player.Character;

	if (not (character)) then
		continue;
	end

	...
end

Give each player’s character an instance which can be used to differentiate them from an NPC.

https://developer.roblox.com/en-us/api-reference/function/Instance/FindFirstChild

An easy way to do this would be to use game.Players:GetPlayerFromCharacter(monster)
If it is nil, then the character is not a real player, and therefor do not run the code to attack it.

local Players = game:GetService("Players")

function findNearestPlayer(Position)
	task.wait(0.5)
	local List = workspace:GetChildren()
	local Distance = 30
	local Torso
	local Human
	local Temp
	local Temp2
	for _, Child in pairs(List) do
		Temp2 = Child
		if Temp2:IsA("Model") and not Temp2 == script.Parent then
			if Temp2:FindFirstChild("HumanoidRootPart") and Players:FindFirstChild(Temp2.Name) then
				Temp = Temp2:FindFirstChild("HumanoidRootPart")
				Human = Temp2:FindFirstChild("Humanoid")
				if Human.Health > 0 then
					if (Temp.Position - Position).Magnitude < Distance then
						Torso = Temp
						Distance = (Temp.Position - Position).Magnitude
					end
				end
			end
		end
	end
	return Torso
end
1 Like

I don’t even read replies, not to mention the post isn’t a “duplicate”, they’re referring to a “value” (like a string value instance), I’m referring to any instance, such as an accessory, limb etc.

I’m probably missing something extremely obvious. However, when I use this code the Monster does not move at all.

Script:

local Players = game:GetService("Players")

function findNearestPlayer(Position)
	task.wait(0.5)
	local List = workspace:GetChildren()
	local Distance = 30
	local Torso = nil
	local Human = nil
	local Temp = nil
	local Temp2 = nil
	for _, Child in pairs(List) do
		Temp2 = Child
		if Temp2:IsA("Model") and not Temp2 == script.Parent then
			if Temp2:FindFirstChild("HumanoidRootPart") and Players:FindFirstChild(Temp2.Name) then
				Temp = Temp2:FindFirstChild("HumanoidRootPart")
				Human = Temp2:FindFirstChild("Humanoid")
				if Human.Health > 0 then
					if (Temp.Position - Position).Magnitude < Distance then
						Torso = Temp
						Distance = (Temp.Position - Position).Magnitude
					end
				end
			end
		end
	end
	return Torso
end

while true do
	local target = findNearestPlayer(script.Parent.HumanoidRootPart.Position)
	if target ~= nil then
		script.Parent.Humanoid:MoveTo(target.Position, target)
	end
end

Snipping this post, not relevant.

While the Instance might not matter, they’re both fundamentally the same. It would still work.

If you want to add to a previously mentioned idea, try quoting the idea and proceeding to add this information. Do not discredit them.

Snipping this post, not relevant.

function findNearestPlayer(Position)
	task.wait(0.5)
	local List = workspace:GetChildren()
	local Distance = 30
	local Torso = nil
	local Human = nil
	local Temp = nil
	local Temp2 = nil
	for _, Child in pairs(List) do
		Temp2 = Child
		if Temp2:IsA("Model") and Temp2 ~= script.Parent then
			if Temp2:FindFirstChild("HumanoidRootPart"):FindFirstChild("RootAttachment") then
				Temp = Temp2:FindFirstChild("HumanoidRootPart")
				Human = Temp2:FindFirstChild("Humanoid")
				if Human.Health > 0 then
					if (Temp.Position - Position).Magnitude < Distance then
						Torso = Temp
						Distance = (Temp.Position - Position).Magnitude
					end
				end
			end
		end
	end
	return Torso
end

while task.wait() do
	local target = findNearestPlayer(script.Parent.HumanoidRootPart.Position)
	if target ~= nil then
		script.Parent.Humanoid:MoveTo(target.Position, target)
	end
end

I get this error:
FindFirstDescendant is not enabled - Server - FollowPlayer:14

Snipping this post, not relevant.

Alright, should be working now.