#4 Place Prefab in a Random Position of the Stage

By GameDevTraum

In this article we analyze the video 4 of the series My First Game in Unity. In this video we created the first Script that will be in charge of placing a Prefab randomly on the stage. The Prefab that we are going to place is the first person controller FPSController of Standard Assets.

We will place the character in front of a door and as there will be several of them on the stage, we will have to make a random choice.

Go to the project’s Main Page

Spawn point of the character

We began by assembling with the prefabricated a scene like the one shown in figure 1.

escena de unity 3d en la que se observa un suelo de cesped con margaritas y cuatro portales.
Fig. 1: Initial arrangement of objects in the scene.

We created an empty GameObject that we’re going to use to mark the position where the player will appear at the start of the game.

crear empty game object en unity 3d. modelo 3d de un portal
Fig. 2: A new Empty GameObject is created to assign the Script.

We are going to call this object “SpawnPoint”.

unity 3d se observa un atardecer y un suelo de cesped con margaritas
Fig. 3: The new GameObject will have the name “SpawnPoint”.

In the inspector we can choose an icon to better visualize the GameObject in the scene.

selección de ícono para gameobject en unity 3d
Fig. 4: We can assign an icon to the GameObject to better visualize it in the scene.

empty gameobject en unity 3d con ícono asignado.
Fig. 5: The GameObject is now displayed with the label selected.

We will create a new Tag to assign to this GameObject. At the top of the inspector we have a drop-down menu called Tag, clicking allows us to choose a Tag to assign or create a new one with “Add Tag”. We click on this option.

menu para añadir tag en en unity 3d.
Fig. 6: Menu for assigning an existing Tag or creating a new one.

In the window that appears click on the plus sign and type the name of the Tag. It is important to note the use of capital letters.

crear nuevo tag en unity 3d.
Fig. 7: We created a new Tag called SpawnPoint.

We select again the GameObject “SpawnPoint” from the hierarchy and in the Tag menu we select the Tag “SpawnPoint” that we just created.

seleccionar tag en unity 3d.
Fig. 8: Assign the created Tag to the GameObject “SpawnPoint”.

Creation of the first Script

Finally we are going to start programming in C#. To start we need to create a C# Script, for this we right click on a folder in the project (I suggest the Script folder we created to organize ourselves), then we go to Create > C# Script, as shown in Figure 9.

crear script c# en unity 3d.
Fig. 9: Creation menu, select C# Script.

We’re going to name the file “GameControl” because it will control the fundamental aspects of our game. The file that is created can be seen in figure 10.

script c# en unity
Fig. 10: The new script is called GameControl without spaces.

Programming usually uses a way of writing as shown in Figure 10, is known as Camel Case and consists of eliminating spaces and distinguish words using capital letters.

We use this notation for script names, variables and methods.

Before starting to program, let’s select a Scripts editor, click on Edit > Preferences.

ventana de preferencias de unity 3d
Fig. 11: Unity preferences window, select the MonoDevelop editor.

For the series My First Game in Unity we used the script editor MonoDevelop, this editor was discontinued, that’s why in the Fundamental Series of Unity Visual Studio is used.

selección de editor de scripts en unity 3d.
Fig. 12: You can choose the editor you like the most, currently the default editor is Visual Studio.

When opening the Script to edit we find some code already written.

In figure 10 the first 3 lines that begin with the word “using” are used to import libraries that will allow us to access certain functionality.

Then comes the definition of a class that bears the name we gave to the Script, in this case GameControl. It also indicates the super class, ie the class from which inherits its behavior, in this case MonoBehaviour. So all the attributes and methods of the MonoBehaviour class will be available for us to use.

The previous paragraph has several object-oriented programming concepts that do not make sense to delve into this article, because it is a fairly extensive topic. However, I believe that the mention of words such as “class”, “attributes” or “super class” may arouse curiosity and encourage the reader to investigate the subject further. At this time I do not have articles on object-oriented programming, although I wish to write them soon.

Then there are two methods defined, the Start method and the Update method. The Start method will run automatically once when the game starts and the Update method will run automatically once in each Frame in the game.

script c# genérico en unity 3d.
Fig. 13: View of a newly created script.

In the region that is between the definition of the class and the definition of the Start method we are going to place all the attributes of the class, that is to say all the variables and objects that we will use so that the Script fulfills its functionality. Some time ago I wrote an article about the basic types of variables that we are going to use in the tutorials.

Let’s write two lines of code, the first is “SerializeField” in square brackets, this is to tell Unity that what comes next is a field to be serialized. Without going into detail this line will make private fields (variables or objects) appear in the inspector.

The next instruction is “private string tag”, with this we are declaring a variable of type string of name “tag” with private visibility.

Visibility is also an object-oriented programming theme, used to hide attributes or methods that are not accessible from a context outside the class. Attributes or methods with public visibility are accessible from other classes.

script c# genérico en unity 3d. definir variables
Fig. 14: A String variable called “tag” is defined.

Asignar Script has a GameObject

For the code to be executed it is not enough to create a Script, we must assign it to at least one GameObject of the hierarchy.

GameControl will be in charge of controlling the basic aspects of the game. In principle it could be assigned to any GameObject that is present during the whole game, but for a better organization we are going to create an Empty GameObject that we will call “Control”.

crear empty game object en unity 3d
Fig. 15: We created a new empty GameObject.

With the new GameObject selected, we drag the GameControl Script into the inspector to add it as a component.

renombrar game object en la jerarquía de unity 3d
Fig. 16: The new GameObject will be called Control.
asignar script c# en el inspector en unity 3d
Fig. 17: We can drag the GameControl Script into the hierarchy of the Control object to assign it.

Figure 18 shows that the script has been added as a component to the Empty GameObject Control.

inspector en unity 3d
Fig. 18: Script is now a component of the Control object.

Another way to accomplish this is by using the Add Component button and searching for the GameControl Script.

add component en unity 3d
Fig. 19: Another way to assign the Script is through the Add Component button.

The reason why in figure 18 we don’t see the String “tag” that we define is because we don’t save the changes in the Script. In figure 20 you can see that in the Script tab there is a circle instead of a cross, this means that there are unsaved changes, you can easily save by pressing CTRL-S.

It is advisable to save frequently enough so that in case of possible failures we do not lose our work.

definicion de variables que se encargarán de colocar el prefab aletoriamente unity 3d.
Fig. 20: The circle on the tab indicates that there are unsaved changes.

After saving the changes we see in the inspector the string “Tag”. In this field we are going to write “SpawnPoint” which is the name we gave to the tag we assigned to GameObject SpawnPoint (figures 5 to 8).

Fig. 21: The serialized string Tag appears in the inspector.
Fig. 22: We can write a value for the String.

Place character prefab randomly

The character will definitely be a GameObject, in particular the Prefab FPSController from Standard Assets. We have to tell Unity somehow which prefab we want to put on stage.

For this we are going to define a private GameObject that we will call “playerPrefab” and we will indicate it as serializable so that it appears in the inspector.

Figure 23 shows the two instructions that allow you to do this.

definicion de variables que se encargarán de colocar el prefab aletoriamente unity 3d.
Fig. 23: We define a GameObject to save the Prefab of the character to instantiate.

In previous videos we had created a Prefab of the FPSController and we had placed it in Assets > Prefabs > Character. This is the Prefab that we are going to place on the stage.

prefab a colocar aleatoriamente en unity 3d
Fig. 25: The prefab FPSController from Standard Assets will be our character.

We take the Prefab FPSController and drag it to the new field in the inspector, as shown in figure 24.

Fig. 24: We assign the prefab in the new space in the inspector.

It’s very important that we keep the reference of the player’s GameObject, for example to destroy it when the game is over. We are going to do this by defining a new private GameObject that we will call “player”.

In this case we will not mark this field as serializable, because it is for internal use of the GameControl Script.

definicion de variables que se encargarán de colocar el prefab aletoriamente unity 3d.
Fig. 26: We define a private GameObject to save the reference of the character we place in the scene.

Then we need to know where we’re going to put the character on stage. For this we created the Empty GameObject that we call SpawnPoint (figures 2 to 5). We are going to make it the son of a door and create a Prefab of the door with the object SpawnPoint.

So each door will have its own SpawnPoint. If we have only one door in the stage, the character will appear in that place, but if we have four doors (as it will be in our case) the character will be able to appear in any of them randomly.

First we need the GameObject SpawnPoint reference, but how many? Since we don’t want to limit the functionality of this script to a fixed number of doors, we’ll simply make it automatically detect how many points of appearance there are and choose one of them randomly with the same probability.

We are going to define a vector or array of GameObjects, that is to say a structure of data that contains several ordered GameObjects, which we will be able to access with an integer value that will indicate its position in the array.

To define this array we use the word GameObject followed by square brackets, as illustrated in figure 27. As this array will contain all the points of appearance of the scenario I will call it “spawnPoints” and I will also define it as private and a Serializable field.

definicion de variables que se encargarán de colocar el prefab aletoriamente unity 3d.
Fig. 27: A GameObjects Array is defined to save the reference of all the points of appearance in the scene.

In the inspector you can see what this data structure looks like. It appears as a drop-down menu that has an integer value called “Size”, which will indicate the size of the array.

As can be seen in figure 29, if we write a number in this variable, we see that there are that many GameObjects fields.

En este punto podríamos hacer que la variable Size sea igual a 4 y asignar manualmente todos los puntos de aparición, pero no queremos estar limitados a eso, queremos lograr que cuando agreguemos o quitemos una puerta, la selección del punto de aparición se haga automáticamente.

Fig. 28: Display of the Array in the inspector, we can indicate the size of the Array.

Fig. 29: When defining the size of the Array, the fields to fill in appear. We could manually place the appearance points.

We will define a new GameObject that will have the reference of the chosen point of appearance, we will call it “selectedSpawnPoint” and we will make it private and serializable to be able to observe it in the inspector.

definicion de variables que se encargarán de colocar el prefab aletoriamente unity 3d.
Fig. 30: Define a GameObject to save the reference of the randomly selected point of appearance.

Programming the behaviour

Until now we have been defining the objects we will need, now we will begin to write instructions that are the ones that will make things happen in our game.

The first instruction will be placed in the Start method and will be responsible for finding all the points of appearance on the stage and save them in the “spawnPoints” array.

Figure 31 shows that the editor helps us by suggesting code as we write. If this doesn’t happen it could be for two reasons, the option “code-autocomplete” is deactivated in the configuration.

The other reason may be a bug in the editor, or that Unity is not connected to the editor. If this happens, try to solve it because not only will we not have the code suggestion but we will not have syntax analysis.

instrucciónes c# que se encarga de colocar el prefab aletoriamente unity 3d. findgameobjectwithtag
Fig. 31: As we write code the editor suggests variables or methods that start with what we write.

To find the references of the points of appearance we are going to use a method of the GameObject class that will allow us to find objects using its tag.

In figures 31 and 32 we see that there are two variants of this method, one returns a single GameObject (figure 31) and the other returns an array containing all GameObjects that have the tag we indicate (figure 32).

Notice how these two methods are only differentiated by an “s” letter.

instrucciónes c# que se encarga de colocar el prefab aletoriamente unity 3d. findgameobjectwithtag
Fig. 32: We are going to use the FindGameObjectsWithTag method of the GameObject class.

The instruction would then be as follows:

spawnPoints=GameObject.FindGameObjectsWithTag(tag);

instrucciónes c# que se encarga de colocar el prefab aletoriamente unity 3d
Fig. 33: The instruction in the Start method is responsible for finding all the points of appearance of the scenario and saving them in the Array spawnPoints.

In the second video of Unity’s fundamental series I analyze this way of finding GameObjects references and four other ways. I also wrote an article about that video going deeper into the information.

Figure 34 shows that when entering game mode, our array is size 1 and contains the GameObject SpawnPoint reference of the hierarchy (highlighted in yellow by Unity itself).

Fig. 34: When entering the game mode, we see that in the inspector is the reference of the point of appearance.

Let’s create some copies of this GameObject with CTRL-D and go back into game mode.

Fig. 35: Copies of the points of appearance are created.

Now we can see that the array is of size 4 and contains all the references of the GameObjects.

Fig. 36: When entering the game mode again, the Array now has four elements and all references are present.

We put a SpawnPoint in every door.

colocar prefab aleatoriamente. posicionar empty objects
Fig. 37: We place a point of appearance on each door.

Select a random element from the array

To choose a random spawn point we need to randomly choose an element from the array. This will be done by defining an integer variable named “rand” that will be equal to a random number between 0 and the number of elements of the array minus 1.

This last part is so because in C# the first element of the array has the position 0 and the last one the position “Length-1” (size of the array minus 1).

To generate a random integer we use the Range method of the Random class and indicate two parameters, the beginning of the interval (value that is included) and the end of the interval (value that is excluded). As shown in figure 38.

instrucciónes c# que se encarga de colocar el prefab aletoriamente unity 3d
Fig. 38: The second instruction generates a random integer between 0 and the number of appearance points minus 1.

Notice how the range of values for this number will automatically adjust to the number of occurrence points in the hierarchy.

The next step is to obtain the reference of the point of appearance that is in the position that defines that random integer. To access the component of an array we use the name of the array and between square brackets the whole number of the position.

The element of the array is assigned to the GameObject selectedSpawnPoint previously defined. We can see this in figure 39.

instrucciónes c# que se encarga de colocar el prefab aletoriamente unity 3d
Fig. 39: The third instruction selects the point of appearance of the array.

In figures 40 and 41 we see two tests of the game in which a different point of appearance has been chosen.

Fig. 40: In this test the spawn point is D.
Fig. 41: In this test the spawn point is B.

The next step is to place the character’s prefab in the position of the selected appearance point.

For this we are going to use the Instantiate method of the MonoBehaviour class (super class of GameControl).

The fourth video in Unity’s fundamental series is about the Instantiate method, although that video is somewhat strange, the article explains in detail how the method works.

The Instantiate method has several versions, we are going to use one that requires the Prefab to instantiate, the position where it is going to be placed and the rotation it will have.

For the prefab we had defined the GameObject “playerPrefab”. While the position and rotation will be read from the GameObject “selectedSpawnPoint”.

The execution of the Instantiate method will return a GameObject which will be the reference of the created GameObject, i.e. the reference of the player. We are going to save this reference in the GameObject “player”, because we will probably use it later.

What was explained in the last three paragraphs is illustrated in the last instruction in figure 42.

instrucciónes c# que se encarga de colocar el prefab aletoriamente unity 3d
Fig. 42: The fourth and final instruction places the character’s prefab at the chosen point of appearance.

As an observation, we can mention the use of the point operator to access the position and rotation attributes, which are defined in the Transform component.

In principle it is not so simple to understand, but as we acquire practice and study a little programming will become something trivial.

Figures 43 and 44 show two tests of the game in which the player appears in different positions.

Fig. 43: The character appears in the door in the upper left corner.

Fig. 44: The character appears in the door in the lower right corner.

Modularization

These four instructions that we have created place the character in one of the doors randomly.

It would be great if we had an instruction called “placeCharacterInARandomDoor” and do all the work. Then we could put a single instruction into start instead of four.

Luckily we can do exactly this by defining a new method.

script c# genérico en unity 3d, método que se encarga de colocar el prefab aletoriamente
Fig. 45: A private method called “placePlayerRandomly” is defined that does not require parameters and does not return parameters.

The method will be called “placePlayerRandomly”, will not require parameters, will not return data, and will be private. The definition of a method with all the enunciated characteristics is illustrated in figure 45.

In the first two videos of this series I used Spanish names, but I think it’s better to get used to using English names, as well as making it easier for me to translate.

script c# genérico en unity 3d, método que se encarga de colocar el prefab aletoriamente
Fig. 46: Move the four instructions to the placePlayerRandomly method.

We are going to select the four instructions that we put in the Start method, we are going to cut them and paste them in this new method, as can be seen in figure 46.

Then in the Start method we make the call to the placePlayerRandomly method, as we see in figure 47.

script c# genérico en unity 3d, método que se encarga de colocar el prefab aletoriamente
Fig. 47: We call placePlayerRandomly in the Start method.

Reset Scene

To easily test the random position feature, I’m going to restart the scene by pressing the R key.

For this we need to add the Namespace UnityEngine.SceneManagement, a Namespace is simply a collection of classes grouped under a name, in this case they are related to the management of scenes in Unity.

We added the Namespace in line 4 shown in figure 48.

script c# genérico en unity 3d. definir variables y métodos. scenemanagement
Fig. 48: We import the SceneManagement library.

To read the keyboard we use an if sentence and the Input class. Video 1 of the Unity Fundamental Series is about reading the keyboard and mouse inputs, in the video article the information is deepened.

Inside the sentence if we execute the static method LoadScene of the class SceneManager and we pass as parameter the number zero, indicating that the scene 0 is loaded. This scene would be the first scene declared in the window Build Settings. In our case we only have one scene so it will just restart.

script c# genérico en unity 3d. definir variables y métodos. loadscene
Fig. 49: In the Update method we read the R key and if it is pressed we load scene 0.

Final details

The last thing we’ll do is modify the rotation of the Empty GameObjects SpawnPoint, so that the blue arrow pointing in the direction opposite the door.

With the E key we select the rotation tool and keeping the SHIFT key pressed we make that the modifications of the angle are with fixed step, if I am not mistaken of 15 degrees. That way if the Y axis angle is for example 0 degrees, we can take it exactly to 90 degrees thanks to that fixed step.

Fig. 50: Rotation of the appearance points so that the character appears as if there was an entrance through the door.

Fig. 51: In this case the blue axis indicates the direction in which the character is looking. In this case it must be rotated 90 degrees clockwise.

To conclude we make a compilation. In the figures 53 and 54 there are two different starts of the game, in each one the player appears in a different door.

colocar prefab aleatoriamente. el personaje aparece en una de las puertas
Fig. 53: Compilation test 1.

colocar prefab aleatoriamente. el personaje aparece en una de las puertas
Fig. 54: Compilation test 2.

Conclusion

In this article we saw how to create the first C# Script that will place the character in a random position on the stage.

All the attributes were analyzed to meet the objective and it was explained what each one was used for.

Modularization is a useful tool to organize our code and make it more intuitive.