How to periodically spawn NPCs that are only visible to a player that is in a region?

I’m trying to make a room where the longer you’re in there, the more rats you’ll see, but the rats aren’t visible to any other players.
If there are multiple players in the room, they will have different amounts of visible rats depending on how long they’ve been in the room

I’m using a remove event that tells the client to spawn a rat but the rats do not appear

Server Script

function checkForNewPlayers()
	for _,part in ipairs(partsInRegion) do
		local player = game.Players:GetPlayerFromCharacter(part.Parent)
		if player then
			if not table.find(playerInBounds,player) then
				if player.Character.Humanoid.Health > 0 then
					table.insert(playerInBounds,player)
				end
			end
		end
	end
end

function removeOldPlayers()
	for playerIndex,player in ipairs(playerInBounds) do
		for partIndex,part in ipairs(partsInRegion) do
			if player == game.Players:GetPlayerFromCharacter(part.Parent) then
				if player.Character.Humanoid.Health > 0 then
					break
				else 
					table.remove(playerInBounds,playerIndex)
					event:FireClient(player, "delete rats")
					break
				end
			elseif partIndex == #partsInRegion then
				table.remove(playerInBounds,playerIndex)
				event:FireClient(player, "delete rats")
			end
		end
	end
end

local spawnratcoro = coroutine.create(function()
	while true do
		wait(5)
		for _,player in ipairs(playerInBounds) do
			if player.Character.Humanoid.Health > 0 then
				event:FireClient(player, "spawn a rat")
			end
		end
	end
end)

local passivecoro = coroutine.create(function()
	while true do
		partsInRegion = workspace:FindPartsInRegion3WithIgnoreList(ratZone,ignoreList,math.huge)
		removeOldPlayers()
		checkForNewPlayers()
		wait(1)
	end
end)

coroutine.resume(passivecoro)
coroutine.resume(spawnratcoro)

Local Script

event.OnClientEvent:Connect(function(Type)
	if Type == "spawn a rat" then
		local ratclone = rat:Clone()
		ratclone.HumanoidRootPart.Position = Vector3.new(math.random(xmin,xmax),-2.179,math.random(zmin,zmax))
		ratclone.randommove.Enabled = true
	end
end)
2 Likes

Wait,pls spawn the rat in server scripts

And then u go to the client to do the player stuff.This is because they wont spawn in client scripts unless it is guis

1 Like

spawning the rats in the clientside should be fine… i made a sandbox AI war before, and i made the AIs clientsided… and nothing was wrong

1 Like

Spawning is on server because u want to spawn,that can be the problem your rats wont spawn.

1 Like

Also,things have changed,u cannot use the same method everytime

1 Like

FE gun kit spawns their bullets on the clientside, and there was NO problem. And also, i did this around 4 days ago.

Yeah,they have to be on client,because it invovles player(bullets are parts)

If u want to do it on client,u can but u cannot use it for models(I personally use servers for spawning because it is convenient)

server

local spawnratcoro = coroutine.create(function()
	while true do
		wait(5)
		for _,player in ipairs(playerInBounds) do
			if player.Character.Humanoid.Health > 0 then
				local ratclone = ratmodel:Clone()
				event:FireClient(player, "spawn a rat", ratclone)
			end
		end
	end
end)

client

event.OnClientEvent:Connect(function(Type, ratclone)
	if Type == "spawn a rat" then
		print("spawning rat")
		ratclone.HumanoidRootPart.Position = Vector3.new(math.random(xmin,xmax),-2.179,math.random(zmin,zmax))
		ratclone.randommove.Enabled = true
	end
end)

at the moment it says “attempt to index nil with ‘HumanoidRootPart’”

1 Like

Of course it will have error,put all that thing on server

but i only want the rat to be visible locally

Ok,for that,oh sorry,put that in client since u want to say the rat to be only vivsible to one

I will go and see what other provlems u have

Bruh,u forgot this line

Ratclone.Parent = game.Workspace

I dont know why i forget this

I swear it’s such a big problem lol, literally no joke everyone forgets it

event.OnClientEvent:Connect(function(Type)
	if Type == "spawn a rat" then
		print("spawning rat")
		local ratclone = rat:Clone()
		ratclone.Parent = game.Workspace
		ratclone.HumanoidRootPart.Position = Vector3.new(math.random(xmin,xmax),-2.179,math.random(zmin,zmax))
		ratclone.randommove.Enabled = true
	end
end)

it’s spawning the rats, can’t tell if it’s only for the player or not since studio won’t connect to the server for some reason
but the rats stay above the ceiling with the initial model, and the random moving script doesn’t enable

If the rats is cloned from the client, then the scripts that moves the rats needs to be changed to a LocalScript, and then the localscript must be parented into the player PlayerScripts… or just make the rats move from the same localscript.

i want the movement of each rat to be independent of one another so should i clone localscripts of each rat and set their parent to playerscripts?
how will the localscripts know which rat they are referring to?

You can put a objectvalue in each LocalScript, and the objectvalue’s value is set to the rat… or like i said, do the movement inside the same script that spawns the npc!

here’s an example


function MovementScript(NPCModel)
local Humanoid = NPCModel.Humanoid
local Torso = NPCModel.Torso

coroutine.wrap(function()

while true do
Humanoid:MoveTo(Torso.Position + Vector3.new(math.random(-10,10),0,math.random(-10,10))
Humanoid.MoveToFinished:Wait() -- might be wrong since i forgot the function name, but it's just an example anyways!
end

end)()

end

event.OnClientEvent:Connect(function(Type)
	if Type == "spawn a rat" then
		print("spawning rat")
		local ratclone = rat:Clone()
		ratclone.Parent = game.Workspace
		ratclone.HumanoidRootPart.Position = Vector3.new(math.random(xmin,xmax),-2.179,math.random(zmin,zmax))
		MovementScript(ratclone)
	end
end)

and that should be it! and remember, it’s just an example!

it works great! just an issue is i can’t get the rats to wait for a bit before moving again for some reason

also, when two rats collide with each other they become suspended in the air for a moment
i have collisions off for all parts of the rat but how does this still happen?
image

I suggest you use collisiongroups to fix the collision issues (register the collisiongroup in server since it won’t work if you do it on the client, then add the clientsided rat parts to the collisiongroup)

and for the movement cooldown, you can use task.wait() or wait(), i believe…

example


function MovementScript(NPCModel)
local Humanoid = NPCModel.Humanoid
local Torso = NPCModel.Torso

coroutine.wrap(function()

while true do
task.wait(math.random(3,6))
Humanoid:MoveTo(Torso.Position + Vector3.new(math.random(-10,10),0,math.random(-10,10))
Humanoid.MoveToFinished:Wait()
end

end)()

end

event.OnClientEvent:Connect(function(Type)
	if Type == "spawn a rat" then
		print("spawning rat")
		local ratclone = rat:Clone()
		ratclone.Parent = game.Workspace
		ratclone.HumanoidRootPart.Position = Vector3.new(math.random(xmin,xmax),-2.179,math.(zmin,zmax))
		MovementScript(ratclone)
	end
end)

1 Like

the whole system works perfectly, thanks!

i parented all the rat clones into a folder and use :ClearAllChildren() when players leave the region

1 Like