I’m trying to write a script for an enemy to come after a player, and this is my code so far:
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local enemy = script.Parent
local enemyRootPart = enemy:FindFirstChild("HumanoidRootPart")
local dmg = 15
local aggroDist = 30
local resetDist = 50
Players.PlayerAdded:Connect(function(plr)
local plrChar = plr:FindFirstChild("Character")
local plrRootPart = plrChar:FindFirstChild("HumanoidRootPart")
if (enemyRootPart.position - plrRootPart.position).magnitude >= aggroDist then
print("Player within range")
end
end)
But it gives me an error on line 12 saying “attempt to index nil.” What am I doing wrong?
It looks like you are trying to access the Character child of plr , but this child may not exist. This is why you are getting the “attempt to index nil” error.
Or, just slap a childadded function in there and it should fix it.
local RunService = game:GetService(“RunService”)
local Players = game:GetService(“Players”)
local enemy = script.Parent
local enemyRootPart = enemy:FindFirstChild(“HumanoidRootPart”)
local dmg = 15
local aggroDist = 30
local resetDist = 50
Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:connect(function(plrChar)
local plrRootPart = plrChar:FindFirstChild(“HumanoidRootPart”)
if (enemyRootPart.position - plrRootPart.position).magnitude >= aggroDist then
print(“Player within range”)
end
end)
end)
If this script is in some type of NPC, it won’t work. PlayerAdded won’t be reliable because it only fires for new players. I strongly suggest moving the script and reprogramming it in a way to handle all enemies at once.
Although this is one way, it wouldn’t make sense to have a PlayerAdded Connection, it isn’t really ideal for what you are trying to do, use a for loop to Iterate over the current existing Players:
for _,player in game.Players:GetPlayers() do -- Iterates through Players
if player.Character then -- If the Players Character Exists
local target = player.Character -- target
local Mag = (enemyRoot.Position - PlrRoot.Position).Magnitude -- Gets Distance
if Mag > resetDist then return end -- ends function if Distance is greater
if Mag < aggrodist then -- If Target is in Range
print"Plr in Range"
end
end
end
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local enemy = script.Parent
local enemyRootPart = enemy:WaitForChild("HumanoidRootPart") -- Just in case it has not loaded in
local dmg = 15
local aggroDist = 30
local resetDist = 50
Players.PlayerAdded:Connect(function(plr)
local plrChar = plr.Character or plr.CharacterAdded:Wait() -- finds Character or Waits for character to be added.
local plrRootPart = plrChar:WaitForChild("HumanoidRootPart") -- Wait For Child
if (enemyRootPart.position - plrRootPart.position).Magnitude <= aggroDist then -- Capitalize M, < less than (if aggroDist is bigger)
print("Player within range")
end
end)
This would half work (unless you think the op is going to add something in the Mag > restDistance if statement.) If you think about the code, one person could be 1cm away from the monster while the other could be a million lightyears away. If the code detects that other person first, its going to stop the code before it could even check who else is nearby.
Another thing is that player:DistanceFromCharacter(position: Vector3) exist!
I tested the code that uses it, and it works how i want it to, the NPC focuses on the Person its targetting until someone closer is there
Plus, you can do this:
local MaxDistance
for _,player in game.Players:GetPlayers() do -- Iterates through Players
if player.Character then -- If the Players Character Exists
local target = player.Character -- target
local Mag = (enemyRoot.Position - PlrRoot.Position).Magnitude -- Gets Distance
if Mag > resetDist then return end -- ends function if Distance is greater
if Mag < aggrodist then -- If Target is in Range
MaxDistance = Mag -- Sets Distance
end
end
end
You could, but a lot of people would avoid Player:GetDistanceFromCharacter