Hey everyone,
I’m making a tycoon game and already (to my suprise) people have pushed the limits to my NPC system. 360 NPCs, we’ve got a lot of server memory usage.
Some things to note:
- There is almost no client lag at all. Streaming Enabled is Enabled as well as other optimization methods.
- The NPCs are tweened on the client, not the server. The server sees it as the NPC “teleporting” to each point to limit server calculations.
- The NPCs have humanoids (for purposes of clothing) but have all humanoid states disabled.
Now, some of you are probably going to cringe at this but, each of the 360 NPCs run on a seperate thread using the spawn() function. It’s served well for 360 NPCs but I’d like to push it further and further. The server memory usage at 360 NPCs is about 1gb. We have 4 players per server that each can have at the momment, no cap to the NPCs.
The NPCs use pathfinding. But the path is only computed once per path. The NPCs only using CFrame and are anchored.
Here is a gif of what the client sees: (Note FPS is lower because of GIF encode)
https://gyazo.com/ec4f2afe123bd932b35cdd3ce2cca99e
https://i.gyazo.com/ec4f2afe123bd932b35cdd3ce2cca99e.mp4
So here is my main question. I’m looking for different ways/suggestions to handle the NPC controllers. I’m welcome to learn any new methods of doing so.
Here is some of the code now:
['Generic Personnel'] = function(plr,npc) local targetSeat = npcUtils.FindStation(plr,"FoundationPersonnel") if targetSeat then targetSeat.Value = npc npc:SetPrimaryPartCFrame(npc:WaitForChild("Moving").Owner.Value.Tycoon.Value.DoubleWorkingDoor.BasicDoubleDoorAnchor.CFrame * CFrame.new(0,1,-5)) local targetObject = targetSeat:FindFirstChildWhichIsA("Seat") if targetObject then pfs.computeAndMove(targetObject.Position,npc) while npc:WaitForChild("Moving").StopNPCLoop.Value == false do npc:SetPrimaryPartCFrame(targetObject.CFrame) npc:WaitForChild("Humanoid").Sit = false wait(math.random(30,90)) if math.random(1,8) == 5 then local targetPatientSeat = npcUtils.FindCaptive(plr,"MedicalBay") if not targetPatientSeat then game.ReplicatedStorage.Remotes.FireHeaderBar:FireClient(npc:WaitForChild("Moving").Owner.Value,"Your staff members are sick. Consider making a medical bay with medical personnel.",Color3.new(255/255,0/255,0/255)) wait(0.1) game.ReplicatedStorage.Remotes.FireHeaderBar:FireClient(npc:WaitForChild("Moving").Owner.Value,"You will be charged $250 if one of your staff members die.",Color3.new(255/255,0/255,0/255)) npc:WaitForChild("Humanoid"):TakeDamage(20) else targetPatientSeat.Value = npc local targetObjectPatientSeat = targetPatientSeat:FindFirstChildWhichIsA("Seat") npc:WaitForChild("Humanoid").Jump = true npcUtils.ClearSeat(targetObject) pfs.computeAndMove(targetObjectPatientSeat.Position,npc) npc:SetPrimaryPartCFrame(targetObjectPatientSeat.CFrame) npc:WaitForChild("Humanoid").Sit = false wait(30) targetPatientSeat.Value = nil npc:WaitForChild("Humanoid").Jump = true npc:SetPrimaryPartCFrame(targetObjectPatientSeat.CFrame) pfs.computeAndMove(targetObject.Position,npc) end end end end end end,
Thank you!
EDIT: I would also like to note that after a while, the server will eventually crash.