I am making a monster in studio for my future horror game. But the In pairs code didn’t work and I don’t know why. Please help.
The AI script:
local caty = script.Parent
local humanoid = caty.Humanoid
caty.PrimaryPart:SetNetworkOwner(nil)
local function IsTarget()
local players = game:GetService("Players")
local maximum = 80
local nearestTarget
for player in pairs(players) do
player.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
if Character then
local target = Character
local distance = (caty.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
if distance < maximum then
nearestTarget = target
maximum = distance
end
end
end)
end)
end
return nearestTarget
end
local function PathSystem(destination)
local PathfindingService = game:GetService("PathfindingService")
local ParamsTable = {
["AgentRadius"] = 8,
["AgentHeight"] = 4.6,
["AgentCanJump"] = false
}
local Path = PathfindingService:CreatePath(ParamsTable)
Path:ComputeAsync(caty.HumanoidRootPart.Position, destination.Position)
return Path
end
local function Kill(target)
local distance = (caty.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
if distance > 3 then
humanoid:MoveTo(target.HumanoidRootPart.Position)
else
local attackAnim = humanoid:LoadAnimation(script.AttackAnim)
attackAnim:Play()
attackAnim.Completed:Wait()
target.Humanoid.Health = 0
end
end
local function WalkTo(destination)
local Path = PathSystem(destination)
if Path.Status == Enum.PathStatus.Success then
for way in pairs(Path:GetWaypoints()) do
local target = IsTarget()
if target and target.Humanoid.Health > 0 then
Kill(target)
break
else
humanoid:MoveTo(way.Position)
humanoid.MoveToFinished:Wait()
end
end
else
humanoid:MoveTo(destination.Position - (caty.HumanoidRootPart.CFrame.LookVector))
end
end
function Loops()
local pathWay = workspace.PathWay:GetChildren()
local randomWay = math.random(1, #pathWay)
WalkTo(pathWay[randomWay])
end
while wait(2) do
Loops()
end
You are trying to loop over an instance. You are trying to loop over the Players instance, which isn’t a table. You want to loop over Players:GetPlayers(), which returns a table.
Additionally, PlayerAdded is an event of Players (the service), not an event for a Player instance.
You’re also connecting events and then trying to return stuff. That’s not going to work.
What you should do is get rid of all of the event stuff, and just loop over players:GetPlayers(). Then, to get the character, you can do Player.Character or Player.CharacterAdded:Wait().
The Wait function is a function on events, just like Connect. Unlike connect, Wait waits for the event to fire.
Player.Character or Player.CharacterAdded:Wait() means it will look at the Player.Character property, which, will be set to nil if the player doesn’t have a character yet. So, if the player doesn’t have a character, its like nil or Player.CharacterAdded:Wait(), so it will wait for a character to be added with the event.
When you connect to an event, the game does not wait for the event to fire, the event will just fire your callback function whenever that thing happens. So, whenever a player’s character gets added CharacterAdded is fired so your callback gets called. It won’t fire the event unless a character is being added after you connect, so if a Character exists it will not call your function.
local caty = script.Parent
local humanoid = caty.Humanoid
caty.PrimaryPart:SetNetworkOwner(nil)
local function IsTarget()
local players = game:GetService("Players"):GetChildren()
local maximum = 80
local nearestTarget
for _, player in pairs(players) do
player.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
if Player.Character then
local target = Player.Character
local distance = (caty.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
if distance < maximum then
nearestTarget = target
maximum = distance
end
end
end)
end)
end
return nearestTarget
end
local function PathSystem(destination)
local PathfindingService = game:GetService("PathfindingService")
local ParamsTable = {
["AgentRadius"] = 8,
["AgentHeight"] = 4.6,
["AgentCanJump"] = false
}
local Path = PathfindingService:CreatePath(ParamsTable)
Path:ComputeAsync(caty.HumanoidRootPart.Position, destination.Position)
return Path
end
local function Kill(target)
local distance = (caty.HumanoidRootPart.Position - target.HumanoidRootPart.Position).Magnitude
if distance > 3 then
humanoid:MoveTo(target.HumanoidRootPart.Position)
else
local attackAnim = humanoid:LoadAnimation(script.AttackAnim)
attackAnim:Play()
attackAnim.Completed:Wait()
target.Humanoid.Health = 0
end
end
local function WalkTo(destination)
local Path = PathSystem(destination)
if Path.Status == Enum.PathStatus.Success then
for way in pairs(Path:GetWaypoints()) do
local target = IsTarget()
if target and target.Humanoid.Health > 0 then
Kill(target)
break
else
humanoid:MoveTo(way.Position)
humanoid.MoveToFinished:Wait()
end
end
else
humanoid:MoveTo(destination.Position - (caty.HumanoidRootPart.CFrame.LookVector))
end
end
function Loops()
local pathWay = workspace.PathWay:GetChildren()
local randomWay = math.random(1, #pathWay)
WalkTo(pathWay[randomWay])
end
while wait(2) do
Loops()
end
You should not be looping over the children in the workspace to get players. Instead you should do this:
local Players = game:GetService("Players")
for _, player in ipairs(Players:GetPlayers()) do
local character = player.Character or player.CharacterAdded:Wait()
-- Code
end
The player Instance doesn’t be have that event, remove that code line so the player will be connected to CharacterAdded event, if that’s what you want.
There are many more issues than this, I pointed them out in my reply above.
@YTDevlog
The loop doesn’t have an index (it has to be for _, player in or for someNameForTheIndex, player in ). You are trying to loop over players which is an instance, you can’t do that. You have to do pairs(players:GetPlayers()). PlayerAdded is an event on the Players service, not on a Player. PlayerAdded fires whenever a new player is added, what you are doing is connecting an event for every player in the game, and, that will use up memory and make your code run multiple times, which you don’t want.
You should do what I said in my post above to fix this stuff.