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
Updated the Module and Server script, thanks for your input.
[+] half of Spawnlocation height / 2
local spawnCFrame = spawnLocation.CFrame + Vector3.new(0, spawnLocation.Size.Y * 2, 0)
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.
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
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.
To incorporate the desired additions, simply follow the documentation.
ForceField | Documentation - Roblox Creator Hub
Debris | Documentation - Roblox Creator Hub
- I recommend parenting
local ForceField = Instance.new("ForceField")
to the NPCs Humanoid. - 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.
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.
Fixed the issue.
Change the NPCSpawner.spawnNPCs function inside the Module to this:
function NPCSpawner.spawnNPCs(npcModel, spawnLocation)
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)
else
warn("Invalid name, expected SpawnLocation")
end
end
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
if #spawnLocations > 0 then
NPCSpawner.spawnNPCs(npcModel, spawnLocations[math.random(1, #spawnLocations)])
end
I have tried something for the forcefield, but it seems like it can’t destroy.
You can force destroy it by doing ForceField:Destroy()
.
I am going to try that also maybe a few things I want in it (ik i said final but I relized something) it has to basically deal with no spawns so if there is no spawns then that would mean the player would be in the air and also teamColor so basically the npc would basically go to a teamcolor if there isnt then basically it would go to any spawnlocation