#10 Place collectables on Unity randomly.


In this article we are going to see a way to place collectable objects in Unity, these objects will be watches that when collecting them will add time in the countdown.

We are going to use the prefabricated clock that we configured in the second article of the project, click here to download the files and see how to configure the prefabs.

Go to the project’s Main Page

Before we begin I invite you to watch the video on which this article is based.

Objective description

We must establish rules and make an exhaustive description of the behavior of the clocks, for example how they will interact with the character, how they will appear on the stage, etc. The better the description, the easier it will be to create a solution using programming.

What we are looking for is that a certain number of clocks appear in the labyrinth. We must make sure that these clocks do not appear inside the walls and do not overlap each other.

To achieve this I am going to reuse the solution from the previous article to place the pedestal in a random position, in the solution I made each piece of the labyrinth know its own geometry and give us a position of its interior if we ask for it.

Fig. 1: The clocks will appear in random positions in the labyrinth.

In addition, I am going to make sure that each piece of the labyrinth can contain only one watch, in this way we do not run the risk of placing two superimposed watches.

To achieve this we must keep a record of the pieces of the labyrinth that have a clock inside, so when we are going to place a new clock, those pieces will not be considered in the selection.

When the character takes a watch, a certain number of seconds will be added to the countdown.

Every time a watch is destroyed, a new one appears on the stage, so that all the time we will have the same number of watches on the stage.


Previous steps

We start by selecting GameObject Control from the hierarchy and assigning it the tag “GameController”. Then select the GameObject FPSController and assign the tag Player.

Fig. 2: Select the control object and assign the tag “GameController”.

Fig. 3: Select the player’s prefab and assign the tag “Player”.

Next we are going to create a new Script called Clock, which we will later assign to the prefabricated clock.

Fig. 4: We create a new script with the name “Clock”.

This script will model the behavior of clocks.

Fields of Clock Script

We are going to define a serialized String that we will call “playerTag”, this variable will contain simply the name of the tag that we have assigned in the player.

Then we will define a float type variable to indicate the life time in seconds of the clock on the stage.

We define a GameObject called labyrinthPiece with “get” and “set” as shown in Figure 5, this way it will be a parameter that can be read and written. I usually like to define public methods to access variables, but this is a very practical way to do it.

Finally we define a GameControl type object because the clock needs to inform the control what is happening.

Fig. 5: We define these fields for use in the solution.

Methods of Clock Script

First we define the SetLifeTime public method with float parameter that we will use so that the GameControl object assigns a certain life time to the clock.

Then there’s the SelfDestruction method that will run when the clock’s life time runs out or the character grabs it.

The Collect method will run when the character picks up the clock, alerts GameControl and then self-destruct.

Finally the OnTriggerEnter method to detect the character, when this happens we will execute the Collect method.

Fig. 6: We define these methods to use in the solution,

Fields in GameControl Script

Let’s go to the GameControl Script and define four serialized fields.

ClockPrefab will contain the prefab of the clock that we will place on the stage. The nClocks integer will indicate how many clocks should be placed on the stage. The float clockLifetime will be the average lifetime of a clock on the stage. Finally the whole timePerClock will indicate how many seconds are added to the Timer after the character takes a clock.

Fig. 7: In GameControl we are going to define some fields to solve the problem.

GameControl Script Methods Statement

The PlaceAllTheClocks method will make sure that it is possible to set the indicated number of clocks and then run the PlaceAClock method as many times as clocks need to be set.

ClockDestroyed will be executed by a clock that has just self-destruct, that way the GameControl Script will be able to re-consider the maze piece where the clock was and place a new clock in a random position.

ClockCollected will be executed by a clock when the character comes into contact with it, this way we can add time to the timer.

Finally, the DestroyAll method will destroy everything that must be destroyed at the end of a game (pedestal, clocks, character, etc.).

Fig. 8: We define some methods in GameControl.

Clock Method Instructions

To start in the Clock Start method we find the reference of the GameControl object, then we invoke the selfDestruction method in a time that is the result of the sum of the life time of the clock with a random value between 0 and 1. In this way we achieve that the clocks are not destroyed in the same frame.

Fig. 9: In the Clock Start method we are going to find the reference of the GameControl component and invoke self-destruction.

In the SelfDestruction method, we inform the GameControl object that a clock has been destroyed and pass the maze piece assigned to the clock as a parameter, so that the GameControl object can remove it from the exclusion list. Then we run the Destroy method with parameter “gameObject” so that the object destroys itself.

Fig. 10: In SelfDestruction we are going to tell the Control that the clock was destroyed and then run the Destroy method.

In the Collect method we are first going to cancel the pending invocation of the selfDestruction method. Then we inform the GameControl object that a clock was collected. Finally we run the selfDestruction method.

Fig. 11: The Collect method informs the event control and then self-destruct.

In the OnTriggerEnter method we are going to ask if the tag of the Collider that touched the clock is the one of the player and if this is true we are going to execute the Collect method.

Fig. 12: If the Collider that comes into contact with the clock has the tag “Player” we will execute the Collect method.

GameControl Methods Instructions

PlaceAllTheClocks Methods

In the PlaceAllTheClocks method of GameControl we will read the amount of labyrinth pieces we have available to place the clocks. If it turns out that more clocks must be placed than the number of labyrinth pieces, let’s make nClocks equal to the number of labyrinth pieces minus one, this way we’ll prevent the program from entering into an infinite loop.

Then we will do a loop executing the PlaceAClock method to place a clock on the stage.

Fig. 13: In the PlaceAllTheClocks method we will put all the clocks on the stage.

StartGame Method

In the StartGame method we are going to create the GameObjects List object (line 182 of figure 14).

To create the object is very important, so much so that in a computer exam in which it was necessary to write code on paper, I forgot to place the new instruction to create the object and I subtracted almost 40 points from 100. When I went to defend my exam they considered that they had exaggerated a little given that it had been my only error and they forgave me.

Fig. 14: In GameControl Start we create the list object and then execute the PlaceAllTheClocks method.

PlaceAClock Method

Returning to the subject of methods, in PlaceAClock we have to randomly choose a piece from the labyrinth assuring us that the piece no longer contains a clock, once we get it, we ask for a random position of its interior. To solve this it is necessary to have solved the exercise of the previous article, in which we created the Script Labyrinth Piece.

The algorithm for placing the watch part can be seen in figure 15.

Fig. 15: The PlaceAClock method will choose a piece from the labyrinth and place the watch.

ClockDestroyed Method

In the ClockDestroyed method we are going to remove from the list the piece of the labyrinth that is passed to us as a parameter and then execute the PlaceAClock method to place a new clock in the scenario.

Fig. 16: In Clock Destroyed we removed the maze piece containing the watch from the list and placed a new watch.

AddSeconds Method of Timer

We need to define a public method within Timer that allows us to add a number of seconds to the timer.

At the end of the script we make the declaration of the AddSeconds method, we will complete it at the end.

Fig. 17: In the Timer Script we are going to add a public method to add seconds to the timer.

Returning to the GameControl Script, in the ClockCollected method we make the call to the AddSeconds method of timer, passing as parameter the whole timePerClock.

Fig. 18: In the Clock Collected method we are going to add seconds to the countdown.

Now let’s go to the EndGame method, where the Destroy lines are, let’s run the DestroyAll method and cut the two Destroy instructions that we had previously placed in other items.

Fig. 19: Let’s go to the EndGame method, cut the destruction instructions and execute the DestroyAll method.

We paste those two instructions into the DestroyAll method and then find all the clocks on stage and destroy them using a foreach loop.

Fig. 20: In DestroyAll we paste the previously cut instructions and remove all clocks from the stage.

Setup Clock Prefab

Now let’s select the prefabricated clock from the project folder and drag it to the scenario to set it up.

Fig. 21: Select the prefab of the clock.

We create the Clock tag and assign it to the GameObject of the clock.

Fig. 22: We created a new Tag called Clock.

Fig. 23: We assign the Clock tag to the prefab of the clock.

Fig. 24: Clock with the assigned tag.

Then drag the Script Clock to its components or use the AddComponent button. Then we introduce “Player” in the tag field (figure 25).

Fig. 25: Assign the Script Clock to the prefab of the clock and enter the player’s Tag.

Let’s go to GameObject Control and enter the new parameters that we had previously defined.

Fig. 26: Select the Control object and set the new parameters in the inspector.

Now let’s complete the AddSeconds method of the Timer Script that we had pending.

Inside we will simply increase the seconds, adjust the minutes and execute the WriteTimer method to update the values.

Fig. 27: Back to the Timer Script and complete the AddSeconds method.

Programming error

At this point an error appeared in the console saying that there is no version of the PlaceAClock method that does not have parameters.

Fig. 28: An error occurs saying that there is no method definition that does not contain parameters.

I go to line 184 of the GameControl Script where the error appeared, in effect we see in figure 29 that the execution of the PlaceAClock method is done without parameters.

Fig. 29: I go to the instruction where the error is located.

I define the integer nPieces with the value of the amount of elements in the labyrinth parts list and enter this integer as a method parameter.

Fig. 30: I define an integer with the number of labyrinth pieces and pass it as parameter to the method.

Bug correction

When I test the game, the clocks didn’t seem to have appeared on the stage. When I paused the simulation and searched the hierarchy, I discovered that they had appeared but were upside down, as shown in figure 31.

Fig. 31: When running the game we find a bug, the clocks appear face down.

To correct this bug I go to the method where a clock is placed on the stage and I look for the instruction in which I make the Instantiate, instruction 173 in figure 32.

Instead of giving the new GameObject the rotation of the Quaternion identity I’m going to give it the rotation that is defined in the prefab of the clock, which when placed on the stage appears correctly oriented.

Fig. 32: I go to the point where I place the clocks on the stage.

Fig. 33: Instead of using Quaternion.Identity I use the rotation defined in Prefab.

Final Details and Test

When I tried the game, I noticed that there were few watches and that they gave up very little time when I picked them up.

In order to balance the elements correctly it is necessary to make several tests and see what works best, in addition this can form part of a system of difficulty in which a high difficulty implies less frequent clocks that deliver little time when picking them up.

Fig. 34: I adjust the values in GameControl to give me more time to collect them.

In figure 35 we have two clocks in front of nostors and the timer marks approximately one minute fifty, the figure 36 was taken moments after grabbing the two watches, we see that the Timer now marks a little more than two minutes ten. This concludes the problem.

Fig. 35: In the scene two clocks are observed in front of the character and the time indicates 1:47.

Fig. 36: After picking up both watches, the time is 2:13.


In this article we have seen how to randomly place collectables in Unity, these collectables were the clocks that when collecting them had to add time to the countdown.

The object GameControl is in charge of placing them on the stage randomly using the solution created in the previous article to place the pedestal randomly in a piece of the labyrinth.

To solve the problem we have created a Script that will model the behavior of the clock and will exchange messages with other Scripts to report events such as a self-destruction or that the character has picked up the clock.

The effect of collectable element we do it simply executing appropriate actions when the character passes over them.

Leave a Comment

Your email address will not be published. Required fields are marked *

Exit mobile version