Hi there! In this beginner-friendly tutorial, I’ll show you how to make an NPC spawn at a random location! Let’s get started!
( Also, ignore that script in the workspace)
First of all, insert at least 2 parts in the Workspace
Next, name the parts equal to the number
of parts you have, for example, if you have 3 parts, you would name one part 1
, the second 2
, and the third 3
. I have used two parts in this tutorial, so I would name one part 1
, and the second part 2
.
Now we go to the properties of both parts and set Anchored
to True
. We can do that by selecting the parts, opening the properties tab, and scrolling down to the Part
category. At the top, you will see Anchored
and if it is set to False, we click on it. If not, we leave it alone.
If Anchored
is set to True:
If Anchored
is set to False:
Now you want to group the parts into a folder, you can accomplish this by selecting all of the parts, using the command: Ctrl + Alt + G
or right-click
on one of the parts selected and click "Group As Folder"
Now that you have a folder, rename the folder to "StartFolder"
and you can accomplish this by selecting the folder and using the command F2
or you can go to properties
and change the name from there.
Now that we have the Folder
set up, I’d recommend changing the Color
of the parts so you can tell which one is which. I will change my first part to Green
and my second part to Blue
.
We will now insert the NPC
using the Moon Animator 2 plugin. You can also insert your own NPC
. When you open the plugin, press the Character Inserter
button and it will open up a GUI
.
You can skip to the Presets
tab, or if you want, you can use your own character as the NPC
, I will use the Presets
for this tutorial. After the opening Presets
tab, you can select R6
or R15
, both of these will work.
R6
R15
I will use R6
for this tutorial. After selecting your rig, create a folder in the ReplicatedStorage
called NpcFolder
. Now select your NPC
and drag it into the folder.
1.
2.
3.
4.
5.
Make sure the HumanoidRootPart is UnAnchored
before proceeding:
Now we want to do the same for the Workspace
. Copy the folder and delete the NPC
.
Now insert a script into the ServerScriptService
.
Name the script “NpcSpawner”
Now open the Script
and delete its content:
print("Hello world!")
Now we will create the variables:
local RS = game:GetService("ReplicatedStorage") -- Gets the service "Replicated Storage"
local startFolder = game.Workspace.StartFolder:GetChildren() -- Gets all the children of the start folder (replace the folder location with your folders' location)
local npcFolder = game.Workspace:WaitForChild("NpcFolder") -- Waits for the child "NpcFolder" located in the Workspace (replace the folder location with your folders' location)
local npcFolderRS = RS:WaitForChild("NpcFolder") -- Gets the NpcFolder in the replicated storage (and again replaces the folder location with your folders' location)
- The
RS
variable is used to get theReplicatedStorage
, which will be used for theNpcFolder
in there. - The two
Folder
variables are the folders in the workspace. ThestartFolder
variable defines the folder in theWorkspace
that contains all of the start parts. After it finds it, it gets all of the children in it by using theGetChildren()
function. The children of my start folder are1
and2
. - The
npcFolderRS
variable is the folder in theReplicatedStorage
. This folder contains theNPC(s)
we want to spawn.
Now that we’ve defined the variables, let’s create a new function
called randomStart()
local function randomStart(npc) -- Creates a local function called "randomStart" with a parameter called "npc"
end
We’ve now created a local function
called randomStart
and it has a parameter
with the name of “npc”. Now, what exactly are functions? Functions shorten lines of code with one word. For example, let’s say you have 100
or even 10
lines of code that you will be using multiple times in your script. To shorten it up, you would use a function. For further detail about functions, please click here. Now that I’ve explained that, we have another thing that may be confusing. These things are called parameters
. Now what are parameters? Parameters are like variables for functions, which you replace when you called that function
. For a further explanation of parameters
, please click here.
Now let’s fill in the function with all the code:
local randomStartResult = startFolder[math.random(1,#startFolder)] -- Creates a local variable called "randomStartResult" and it uses math.random to get 1 random child of the startFolder to be used as a start point
local humRoot = npc:WaitForChild("HumanoidRootPart") -- Waits for the child "HumanoidRootPart" of the npc
npc.Parent = npcFolder -- Makes the parent of the npc the npcFolder in the Workspace
humRoot.CFrame = randomStartResult.CFrame -- Makes it so that the HumanoidRootPart's CFrame is the randomStartResult's CFrame
print(randomStartResult) -- Prints the number that is the randomStartResult (Not Necessary)
return randomStartResult -- Returns the randomStartResult
Whew! That was a lot of code! You may be confused about some of these and what they do, so let me explain them.
-
randomStartResult
looks quite complicated, and it can be. So I’ll make this explanation short. it uses the folderstartFolder
to get a random start using math.random(). It uses#startFolder
to get the folder and make it work withmath.random()
, asmath.random()
can only be used withnumbers
. -
The
humRoot
variable is quite simple. It uses the parameternpc
to wait for its child (using WaitForChild) and the child is theHumanoidRootPart
andhumRoot
is short forHumanoidRootPart
. -
The next line of code is very brief, but it is also very important. In this line, we use
npc
again but we add something after it, called.Parent
. What this does is change the npc’sParent
tonpcFolder
, which is how we make thenpc
appear physically. The npc’s currentParent
is thenpcFolderRS
, but it will change tonpcFolder
after this is run. -
Now there is something new introduced, this being
CFrame
. What is theCFrame
?CFrame
describes theobject
's position. What we use this for in this script is to make theCFrame
of thehumRoot
the same as therandomStartResult
CFrame, so that thenpc
can spawn at the random start part.
For more information aboutCFrames
, click here. -
Now we have a line that says:
print(randomStartResult)
. This line is not necessary as it does not affect anything except the output, and this can be used to keep track of therandom start part
. If you keep this line and run the completedscript,
the output shouldprint
thepart
chosen, if you have5
parts, it can print from1-5
. It prints anumber
because therandomStartResult
is anumber
. -
Now we’re onto the last line of this
function
! This line is also very brief. What this line does is return therandomStartResul
t so themath.random()
can actually work.
We’ve finished the long and hard part of this tutorial, and from here this becomes very simple!
randomStart(npcFolderRS:WaitForChild("R6")) -- Replace the parameter with your npc that you want to spawn (With its location and name)
This line is very simple and it shows how useful functions
can be! We start off by calling the function
we created, and in the parentheses (which is known as the scope) we put in the NPC
we want to spawn
. We have to get its location
to spawn it, which should be in the folder
that is located in the ReplicatedStorage
. WaitForChild()
isn’t needed since this is a server script and not a local script, so you can define it without using this function
.
And that’s it! Thanks for reading this tutorial and I’ll (hopefully) make more tutorials in the future. In my next tutorial, I’ll teach you how to make the NPC
move to waypoints
! A video of this working and the full code are listed below! If you think anything in here is inaccurate/misleading, please let me know!
Video of NPC
spawning on 1
:
Video of NPC
spawning on 2
:
Full Code:
local RS = game:GetService("ReplicatedStorage") -- Gets the service "Replicated Storage"
local startFolder = game.Workspace.StartFolder:GetChildren() -- Gets all the children of the start folder (replace the folder location with your folders' location)
local npcFolder = game.Workspace:WaitForChild("NPCFolder") -- Waits for the child "NPCFolder" located in the Workspace (replace the folder location with your folders' location)
local npcFolderRS = RS:WaitForChild("NPCFolder") -- Gets the NPCFolder in the replicated storage (and again replaces the folder location with your folders' location)
local function randomStart(npc) -- Creates a local function called "randomStart" with a parameter called "npc"
local randomStartResult = startFolder[math.random(1,#startFolder)] -- Creates a local variable called "randomStartResult" and it uses math.random to get 1 random child of the startFolder to be used as a start point
local humRoot = npc:WaitForChild("HumanoidRootPart") -- Waits for the child "HumanoidRootPart" of the npc
npc.Parent = npcFolder -- Makes the parent of the npc the npcFolder in the Workspace
humRoot.CFrame = randomStartResult.CFrame -- Makes it so that the HumanoidRootPart's CFrame is the randomStartResult's CFrame
print(randomStartResult) -- Prints the number that is the randomStartResult (Not Necessary)
return randomStartResult -- Returns the randomStartResult
end
randomStart(npcFolderRS:WaitForChild("R6")) -- Replace the parameter with your npc that you want to spawn (With its location and name)