How can I make a Player Like Spawn But for NPCs

So, I’ve been trying to make a code or module for NPCs that Spawns like Players. Not like a class but like an NPC going to spawn locations if not then going to the air. but if like the spawn usually small then the player goes to the center, so if possible have the NPC to do that, and big ones for players they get to spawn anywhere based on the spawn location’s size. Can you guys help me with that also it is a project that I’m currently working on. (Please make it a module)

I’m just asking you guys since you guys are intelligent (some are not but I never judge by a book by its cover) except for me. I don’t really get that much time because of school :disappointed_relieved:. So please.

4 Likes

I’m so sorry but I cannot understand what you’re saying (My attention span is also short). Based on the title you want an NPC spawner? If I’m wrong please do correct me but summarize your statement. If I am partially correct you can fill In details I missed

2 Likes

he means he wants to spawn npc’s in the same way that players spawn

3 Likes

Module

local NPCSpawner = {}

-- Function to spawn NPC at a specific location
local function spawnNPC(npc, targetCFrame)
	local newNPC = npc:Clone()

	-- Ensure npc has a PrimaryPart
	if not newNPC.PrimaryPart then
		warn("NPC model does not have a PrimaryPart")
		return
	end

	-- Set the position of the NPC using PivotTo
	newNPC.Parent = workspace
	newNPC:SetPrimaryPartCFrame(targetCFrame)
end

-- Main function to spawn NPCs
function NPCSpawner.spawnNPCs(npcModel, spawnLocations)
	for _, spawnLocation in pairs(spawnLocations) do
		if spawnLocation:IsA("SpawnLocation") then
			local spawnCFrame = spawnLocation.CFrame + Vector3.new(0, spawnLocation.Size.Y * 2, 0)
			spawnNPC(npcModel, spawnCFrame)
			break
		else
			warn("Detected object is not a SpawnLocation")
		end
	end
end

return NPCSpawner

Server

local NPCSpawner = require(game:GetService("ServerScriptService").NPCSpawnerModule)
local npcModel = game.ServerStorage.NPCModel -- Replace with your NPC model or change this to a for loop.

-- Find all SpawnLocation objects in workspace
local spawnLocations = {}

for _, descendant in pairs(workspace:GetDescendants()) do
	if descendant:IsA("SpawnLocation") then
		table.insert(spawnLocations, descendant)
	end
end

NPCSpawner.spawnNPCs(npcModel, spawnLocations)
2 Likes

Your code works however you should use the PivotTo method and you should also keep in mind your code will tp the NPC into the ground. You can account for this by calculating the height of the npc legs + hrp height/2

2 Likes

Updated the Module and Server script, thanks for your input.

1 Like

[+] half of Spawnlocation height / 2 :smirk:

1 Like
local spawnCFrame = spawnLocation.CFrame + Vector3.new(0, spawnLocation.Size.Y * 2, 0)
1 Like

Your module works, but also (this is optional) can you make it where maybe idk if multiple NPCs are going to be spawned can you make it where all those NPCs will be stacked or randomly spawned. its kind of where that devform was about the upgraded the size of it and saying that allot of players can now be stacked up or something like that let me try to find it.

See where I’m going with @DangerRangerJJD ?

Do you want NPCs spawning on top of each other?

yes and also including yk the randomly spawned areas base on the spawn size if you can make that happen

1 Like

Change Logs:

  • Replaced requirement 'IsA(“SpawnLocation”) with '.Name == “SpawnLocation”
  • Added Raycast function to check for NPCs in the same location
  • Added random position within SpawnLocation size/region function
  • Added declarations that will move the NPC based on the new functions

Module

local NPCSpawner = {}

-- Function to perform a raycast to check for an NPC at the spawn location
local function getNPCAtLocation(spawnLocation)
	local rayOrigin = spawnLocation.Position + Vector3.new(0, spawnLocation.Size.Y * 2, 0)
	local rayDirection = Vector3.new(0, -spawnLocation.Size.Y * 2, 0)
	local ray = Ray.new(rayOrigin, rayDirection)
	local hitPart, hitPosition = workspace:FindPartOnRay(ray)

	if hitPart and hitPart.Parent and hitPart.Parent:IsA("Model") and hitPart.Parent.PrimaryPart then
		return hitPart.Parent
	end
	return nil
end

-- Function to spawn NPC at a specific location
local function spawnNPC(npc, targetCFrame)
	local newNPC = npc:Clone()

	-- Ensure npc has a PrimaryPart
	if not newNPC.PrimaryPart then
		newNPC.PrimaryPart = newNPC:FindFirstChild("HumanoidRootPart")
	end

	-- Set the position of the NPC using PivotTo
	newNPC.Parent = workspace
	newNPC:SetPrimaryPartCFrame(targetCFrame)
end

-- Function to generate a random position within the size of the spawnLocation
local function getRandomPositionInSpawnLocation(spawnLocation)
	local spawnPos = spawnLocation.Position
	local spawnSize = spawnLocation.Size

	-- Generate random offsets within the range of half the spawnLocation's size
	local offsetX = (math.random() - 0.5) * spawnSize.X / 2
	local offsetY = (math.random() - 0.5) * spawnSize.Y / 2 
	local offsetZ = (math.random() - 0.5) * spawnSize.Z / 2

	return spawnPos + Vector3.new(offsetX, offsetY, offsetZ)
end

-- Main function to spawn NPCs
function NPCSpawner.spawnNPCs(npcModel, spawnLocations)
	for _, spawnLocation in pairs(spawnLocations) do
		if spawnLocation.Name == "SpawnLocation" then
			local existingNPC = getNPCAtLocation(spawnLocation)

			local spawnCFrame
			if existingNPC then
				-- Spawn on top of existing NPC
				spawnCFrame = existingNPC.PrimaryPart.CFrame + Vector3.new(0, existingNPC.PrimaryPart.Size.Y * 2, 0)
			else
				-- Spawn at a random position within the size of the spawnLocation
				local randomPosition = getRandomPositionInSpawnLocation(spawnLocation)
				spawnCFrame = CFrame.new(randomPosition) + Vector3.new(0, spawnLocation.Size.Y * 2, 0)
			end

			spawnNPC(npcModel, spawnCFrame)
			break
		else
			warn("Detected object is not a SpawnLocation")
		end
	end
end

return NPCSpawner

Script

local NPCSpawner = require(game:GetService("ServerScriptService").NPCSpawnerModule)
local npcModel = game.ServerStorage.NPCModel -- Replace with your NPC model or change this to a for loop.

-- Find all SpawnLocation objects in workspace
local spawnLocations = {}

for _, descendant in pairs(workspace:GetDescendants()) do
	if descendant.Name == "SpawnLocation" then
		table.insert(spawnLocations, descendant)
	end
end

NPCSpawner.spawnNPCs(npcModel, spawnLocations)

I love it, but maybe some things so you know roblox used to have the spawnlocation size 6, 1, 6 and players used to stack can you also make it detect with that size so it stacks, but I like it. May you add that addition? Please. But I’m liking it so far.

You should make this a post in community resources.

It is off topic to post updates and such in this post.

I am confused. The NPCs do stack, but because the initial location is chosen randomly within the radius of the SpawnLocation, it’s less likely for them to spawn on top of each other. However, in some cases, they do.

nevermind. don’t need to change anything. Anyways thank you. But the final additions Forcefields from the spawnlocations duration and randomly selecting a random spawnlocation. Sorry for my confusion.

1 Like

To incorporate the desired additions, simply follow the documentation.

ForceField | Documentation - Roblox Creator Hub
Debris | Documentation - Roblox Creator Hub

  1. I recommend parenting local ForceField = Instance.new("ForceField") to the NPCs Humanoid.
  2. The forcefield can be added to the DebrisService as a new Debris and for the duration of your SpawnLocation property Duration or a custom number. DebrisService:AddItem(ForceField, SpawnLocation.Duration or Players.RespawnTime or 5)

NPCs spawn randomly based on the SpawnLocations you have as a descendant of Workspace.

1 Like

Well, you say that but when I tested it. It seems like they don’t. They just choose an option only one spawn location and not the others. Again, they just choose one spawn location, and I tried running it over and over and they perhaps just because it’s in a for loop.

1 Like