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
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.
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.
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
-- 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
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
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
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