Hi there guys! I’ve searched the whole documentation for the past days and couldn’t find a working civilian npc system just like in Retail Tycoon / any other game that has that feature.
I’ve tried to recreate the same mechanics using AI and re-editing the script to make it work.
I am saying this now because i’m not the best scripter, some things you might wanna do differently but for the starting point of having an npc that goes to the Cashier Desk and after some time he goes and sits on a free chair at the table & leaves it’s good.
[P.S For this tutorial we assume you are using the customers for a Tycoon game]
First of all we need to do the following things :
Inside the [Tycoons] folder → [YourTycoonName] add the following things :
- Tables model, CashierDesk & Exit [The cashier desk and Exit are just transparent parts]
CashierDesk must have 2 attributes added : Position & Occupants
Occupants - Number attribute
Position - Vector3 attribute with the position of the cashierDesk
The [Tables] model should look like this when opened :
Inside [Tables] model we will find the Tables [parts or meshparts, whatever you want them to be], and inside each Table, we will have a model called Chairs with the corresponding chairs (having a Seat also) [numbered from 1-x so it helps us when debugging]
The Chairs inside Chairs Model must also have an attribute added to them :
IsOccupied - Boolean Attribute [True/False]
The [CashierDesk] & [Exit] will look like this in our game : [you can turn the transparency to 0 if needed]
CashierDesk [Green transparent part]
Exit Part [Red transparent part]
After that add a Part inside Workspace, call it NPCSpawnZone just like so :
The NPCSpawnZone will look something like this and it will be placed wherever you want : [Make it fully transparent with the CanCollide turned off]
Good! now most of the stuff is already there, meaning we just need to import the NPC’s somewhere and make them move to our designated location
First of all, to add our NPC’s we need to :
- Open ServerStorage → Create a NPC Folder → Add NPC’s there, from 1-x [depends on how many you want]
It should look something like this:
After that we head over to → ServerScriptService Folder & create a script called “CustomerNPCS”
Now the scripting part starts, we open the script called “CustomerNPCS” and do this :
- We define the services and the variables right at the top :
-- Services
local ServerStorage = game:GetService("ServerStorage")
local WorkspaceFolder = game:GetService("Workspace")
local PathfindingService = game:GetService("PathfindingService")
-- Variables
local tycoonsFolder = WorkspaceFolder:FindFirstChild("Tycoons")
local npcSpawnZone = WorkspaceFolder.NPCSpawnZone -- Reference to your NPC Spawn Zone
local tycoons = {} -- Create an empty table to store valid tycoon models
local npcFolder = ServerStorage:FindFirstChild("NPC")
local maxCashierCapacity = 5 -- How many NPC's will get in the line at the cashierDesk
local maxChairCapacity = 24 -- Max capacity of chairs where NPC's can sit
- After that we filter only valid tycoon models :
for _, child in ipairs(tycoonsFolder:GetChildren()) do
if child:IsA("Model") and (child.Name:match("Tycoon%d")) then
table.insert(tycoons, child) -- Add only tycoon models to the list
end
end
- Then we create the function so the NPC’s can walk using PathFinding :
local function moveToPosition(npc, targetPosition)
local humanoid = npc:FindFirstChild("Humanoid")
if humanoid then
local path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentJumpHeight = 10,
AgentMaxSlope = 45,
})
-- Compute the path to the target position
path:ComputeAsync(npc.HumanoidRootPart.Position, targetPosition)
-- Get waypoints and move the NPC
local waypoints = path:GetWaypoints()
for _, waypoint in ipairs(waypoints) do
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
end
else
warn("Humanoid not found for NPC")
end
end
- We then create a function for the NPC to find a free chair inside the Tycoon :
local function findFreeChair(tycoon)
local freeChairs = {} -- Create a table to hold free chairs
local tables = tycoon.Tables:GetChildren()
for _, tableModel in pairs(tables) do
local chairs = tableModel.Chairs:GetChildren()
for _, chair in pairs(chairs) do
if not chair:GetAttribute("IsOccupied") then
table.insert(freeChairs, chair) -- Add free chair to the list
print("Free chair found: ", chair.Name) -- Debugging
end
end
end
if #freeChairs > 0 then
-- Randomly select a free chair
local randomIndex = math.random(1, #freeChairs)
return freeChairs[randomIndex] -- Return a random free chair
else
print("No free chair found in tycoon: ", tycoon.Name) -- Debugging
return nil -- No free chair found
end
end
- If the NPC doesn’t find a free chair, in any of the Tycoons → Tycoon1/2/3/4… then we make it wander around :
local function npcWander(npc, currentTycoon)
-- Move NPC randomly around the map (use moveToPosition here)
local randomPosition = Vector3.new(
math.random(-50, 50),
0,
math.random(-50, 50)
)
moveToPosition(npc, randomPosition)
end
- Then we give him a behavior for when it enters the tycoon (Go to cashierDesk → wait a bit → go to the tables → find a free chair to sit → wait a bit → exit the tycoon) :
local function npcEnterTycoon(npc, tycoon)
local cashierDesk = tycoon.CashierDesk
-- Check cashier capacity
local occupants = cashierDesk:GetAttribute("Occupants") or 0
if occupants < maxCashierCapacity then
-- Move NPC to cashier desk
moveToPosition(npc, cashierDesk.Position)
cashierDesk:SetAttribute("Occupants", occupants + 1)
wait(3) -- Wait for 3 seconds at cashier
-- Find a free chair
local freeChair = findFreeChair(tycoon)
local humanoid = npc:FindFirstChild("Humanoid")
if freeChair then
-- Move NPC to the free chair
moveToPosition(npc, freeChair.Position)
wait(2) -- Time to sit down
-- Set the chair to occupied
freeChair:SetAttribute("IsOccupied", true)
print(npc.Name .. " is now sitting in " .. freeChair.Name) -- Debugging
wait(math.random(5, 30)) -- NPC sits for min 5 seconds to 30 seconds
-- Free the chair and update attribute
freeChair:SetAttribute("IsOccupied", false)
humanoid.Sit = false
print(npc.Name .. " has left the chair " .. freeChair.Name) -- Debugging
cashierDesk:SetAttribute("Occupants", occupants - 1) -- Free cashier spot
-- NPC leaves the tycoon
moveToPosition(npc, tycoon.Exit.Position) -- Move to exit
else
-- No free chair, try another tycoon
npcWander(npc, tycoon)
end
else
-- Cashier is full, try another tycoon
npcWander(npc, tycoon)
end
end
- And we also need to make a reference to the NPC spawn point & to also spawn them :
-- Reference to the SpawnPoint
local spawnPoint = WorkspaceFolder:FindFirstChild("NPCSpawnzone")
-- Adjusted NPC spawning function
local function spawnNPC()
local npcNames = {"NPC1", "NPC2", "NPC3", "NPC4", "NPC5"} -- Table of NPC names
while true do
wait(math.random(5, 10)) -- Spawn an NPC every 5-10 seconds
-- Randomly select an NPC name from the table
local randomNpcName = npcNames[math.random(1, #npcNames)]
local npc = ServerStorage.NPC:FindFirstChild(randomNpcName):Clone() -- Clone the selected NPC
-- Set NPC's position near the spawn zone
local spawnPosition = npcSpawnZone.Position + Vector3.new(
math.random(-5, 5), -- Randomize x position
0, -- Keep the y position the same (assuming it's on the ground)
math.random(-5, 5) -- Randomize z position
)
npc:SetPrimaryPartCFrame(CFrame.new(spawnPosition)) -- Set the NPC position
npc.Parent = WorkspaceFolder -- You can make them spawn anywhere, just change the variable from WorkspaceFolder to whatever you want
-- Enter a random tycoon to start
npcEnterTycoon(npc, tycoons[math.random(1, #tycoons)])
end
end
-- Start spawning NPCs
spawn(function()
spawnNPC()
end)
Hope this little tutorial helped you guys, I’m open to suggestions / edits to make it work better, as i’ve said it’s a STARTING POINT for thoes who want to start working on a game that includes NPC’s and can’t find anything related [If you’re new to scripting or you haven’t ever scripted this tutorial is pretty much good for you]
I’ve attached the .rblxm file if you don’t want to follow along and just copy-paste everything, it’s up to you guys but I would recommend you check out the tutorial so you know where everything goes.
CustomerNPC-javasquid.rbxm (74.9 KB)