#10 Place collectables on Unity randomly.

Updated information about this project

This arti­cle belongs to a series that con­sist on mak­ing a first per­son game about find­ing objects inside a maze. It's one of my very first series from the chan­nel. Now I reworked this project and you can down­load it to import in your own Uni­ty project. Some day I will make a new series about this project, sub­scribe to my chan­nel to see all the fresh con­tent about Blender, Uni­ty and pro­gram­ming.

Follow me on itch.io and download the source code of this project

YOU CAN TRY THIS GAME HERE, IT MAY TAKE A LITTLE WHILE TO LOAD
🔻

MOVEMENT: WASD CAMERA LOOK: MOUSE

Introduction of the old article

In this arti­cle we are going to see a way to place col­lec­table objects in Uni­ty, these objects will be watch­es that when col­lect­ing them will add time in the countdown.

We are going to use the pre­fab­ri­cat­ed clock that we con­fig­ured in the sec­ond arti­cle of the project, click here to down­load the files and see how to con­fig­ure the pre­fabs.

Go to the project's Main Page

Video related to this article

Before we begin I invite you to watch this video. 


Objective description

We must estab­lish rules and make an exhaus­tive descrip­tion of the behav­ior of the clocks, for exam­ple how they will inter­act with the char­ac­ter, how they will appear on the stage, etc. The bet­ter the descrip­tion, the eas­i­er it will be to cre­ate a solu­tion using programming.

What we are look­ing for is that a cer­tain num­ber of clocks appear in the labyrinth. We must make sure that these clocks do not appear inside the walls and do not over­lap each other.

To achieve this I am going to reuse the solu­tion from the pre­vi­ous arti­cle to place the pedestal in a ran­dom posi­tion, in the solu­tion I made each piece of the labyrinth know its own geom­e­try and give us a posi­tion of its inte­ri­or if we ask for it.

reloj colocado aleatoriamente en unity
Fig. 1: The clocks will appear in ran­dom posi­tions in the labyrinth.

In addi­tion, I am going to make sure that each piece of the labyrinth can con­tain only one watch, in this way we do not run the risk of plac­ing two super­im­posed 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 con­sid­ered in the selection.

When the char­ac­ter takes a watch, a cer­tain num­ber of sec­onds 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 num­ber of watch­es on the stage.

Resolution

Previous steps

We start by select­ing GameOb­ject Con­trol from the hier­ar­chy and assign­ing it the tag "Game­Con­troller". Then select the GameOb­ject FPSCon­troller and assign the tag Player.

asignacion de tags en unity desde la ventana inspector
Fig. 2: Select the con­trol object and assign the tag "Game­Con­troller".

asignacion de tags en unity desde la ventana inspector
Fig. 3: Select the player's pre­fab and assign the tag "Play­er".

Next we are going to cre­ate a new Script called Clock, which we will lat­er assign to the pre­fab­ri­cat­ed clock.

creacion de scripts c# en unity
Fig. 4: We cre­ate a new script with the name "Clock".

This script will mod­el the behav­ior of clocks.

Fields of Clock Script

We are going to define a seri­al­ized String that we will call "play­erTag", this vari­able will con­tain sim­ply the name of the tag that we have assigned in the player.

Then we will define a float type vari­able to indi­cate the life time in sec­onds of the clock on the stage.

We define a GameOb­ject called labyrinth­Piece with "get" and "set" as shown in Fig­ure 5, this way it will be a para­me­ter that can be read and writ­ten. I usu­al­ly like to define pub­lic meth­ods to access vari­ables, but this is a very prac­ti­cal way to do it.

Final­ly we define a Game­Con­trol type object because the clock needs to inform the con­trol what is happening.

script c# en unity para controlar la aparicion aleatoria de relojes en el escenario
Fig. 5: We define these fields for use in the solution.

Methods of Clock Script

First we define the SetLife­Time pub­lic method with float para­me­ter that we will use so that the Game­Con­trol object assigns a cer­tain life time to the clock.

Then there's the Self­De­struc­tion method that will run when the clock's life time runs out or the char­ac­ter grabs it.

The Col­lect method will run when the char­ac­ter picks up the clock, alerts Game­Con­trol and then self-destruct.

Final­ly the OnTrig­ger­Enter method to detect the char­ac­ter, when this hap­pens we will exe­cute the Col­lect method.

script c# en unity para controlar la aparicion aleatoria de relojes en el escenario
Fig. 6: We define these meth­ods to use in the solution,

Fields in GameControl Script

Let's go to the Game­Con­trol Script and define four seri­al­ized fields.

Clock­Pre­fab will con­tain the pre­fab of the clock that we will place on the stage. The nClocks inte­ger will indi­cate how many clocks should be placed on the stage. The float clock­Life­time will be the aver­age life­time of a clock on the stage. Final­ly the whole timePer­Clock will indi­cate how many sec­onds are added to the Timer after the char­ac­ter takes a clock.

campos de la clase gamecontrol que se usaran para resolver el problema
Fig. 7: In Game­Con­trol we are going to define some fields to solve the problem.

GameControl Script Methods Statement

The PlaceAllThe­Clocks method will make sure that it is pos­si­ble to set the indi­cat­ed num­ber of clocks and then run the PlaceA­Clock method as many times as clocks need to be set.

Clock­De­stroyed will be exe­cut­ed by a clock that has just self-destruct, that way the Game­Con­trol Script will be able to re-con­sid­er the maze piece where the clock was and place a new clock in a ran­dom position.

Clock­Col­lect­ed will be exe­cut­ed by a clock when the char­ac­ter comes into con­tact with it, this way we can add time to the timer.

Final­ly, the Destroy­All method will destroy every­thing that must be destroyed at the end of a game (pedestal, clocks, char­ac­ter, etc.).

metodos de la clase gamecontrol que se usaran para resolver el problema
Fig. 8: We define some meth­ods in GameControl.

Clock Method Instructions

To start in the Clock Start method we find the ref­er­ence of the Game­Con­trol object, then we invoke the self­De­struc­tion method in a time that is the result of the sum of the life time of the clock with a ran­dom val­ue between 0 and 1. In this way we achieve that the clocks are not destroyed in the same frame.

metodo start del reloj, encontrar referencias, invocar autodestruccion
Fig. 9: In the Clock Start method we are going to find the ref­er­ence of the Game­Con­trol com­po­nent and invoke self-destruction.

In the Self­De­struc­tion method, we inform the Game­Con­trol object that a clock has been destroyed and pass the maze piece assigned to the clock as a para­me­ter, so that the Game­Con­trol object can remove it from the exclu­sion list. Then we run the Destroy method with para­me­ter "gameOb­ject" so that the object destroys itself.

metodo auto destruccion del reloj
Fig. 10: In Self­De­struc­tion we are going to tell the Con­trol that the clock was destroyed and then run the Destroy method.

In the Col­lect method we are first going to can­cel the pend­ing invo­ca­tion of the self­De­struc­tion method. Then we inform the Game­Con­trol object that a clock was col­lect­ed. Final­ly we run the self­De­struc­tion method.

metodo collect para un reloj que aparece en el escenario aleatoriamente
Fig. 11: The Col­lect method informs the event con­trol and then self-destruct.

In the OnTrig­ger­Enter method we are going to ask if the tag of the Col­lid­er that touched the clock is the one of the play­er and if this is true we are going to exe­cute the Col­lect method.

metodo ontriggerenter para un reloj que aparece en el escenario aleatoriamente
Fig. 12: If the Col­lid­er that comes into con­tact with the clock has the tag "Play­er" we will exe­cute the Col­lect method.

GameControl Methods Instructions

PlaceAllTheClocks Methods

In the PlaceAllThe­Clocks method of Game­Con­trol we will read the amount of labyrinth pieces we have avail­able to place the clocks. If it turns out that more clocks must be placed than the num­ber of labyrinth pieces, let's make nClocks equal to the num­ber of labyrinth pieces minus one, this way we'll pre­vent the pro­gram from enter­ing into an infi­nite loop.

Then we will do a loop exe­cut­ing the PlaceA­Clock method to place a clock on the stage.

metodo place all the clocks para colocar todos los relojes aleatoriamente en el escenario
Fig. 13: In the PlaceAllThe­Clocks method we will put all the clocks on the stage.

StartGame Method

In the StartGame method we are going to cre­ate the GameOb­jects List object (line 182 of fig­ure 14).

To cre­ate the object is very impor­tant, so much so that in a com­put­er exam in which it was nec­es­sary to write code on paper, I for­got to place the new instruc­tion to cre­ate the object and I sub­tract­ed almost 40 points from 100. When I went to defend my exam they con­sid­ered that they had exag­ger­at­ed a lit­tle giv­en that it had been my only error and they for­gave me.

metodo start de gamecontrol, juego del laberinto en unity
Fig. 14: In Game­Con­trol Start we cre­ate the list object and then exe­cute the PlaceAllThe­Clocks method.

PlaceAClock Method

Return­ing to the sub­ject of meth­ods, in PlaceA­Clock we have to ran­dom­ly choose a piece from the labyrinth assur­ing us that the piece no longer con­tains a clock, once we get it, we ask for a ran­dom posi­tion of its inte­ri­or. To solve this it is nec­es­sary to have solved the exer­cise of the pre­vi­ous arti­cle, in which we cre­at­ed the Script Labyrinth Piece.

The algo­rithm for plac­ing the watch part can be seen in fig­ure 15.

metodo place a clock para colocar un reloj aleatoriamente en el escenario
Fig. 15: The PlaceA­Clock method will choose a piece from the labyrinth and place the watch.

ClockDestroyed Method

In the Clock­De­stroyed method we are going to remove from the list the piece of the labyrinth that is passed to us as a para­me­ter and then exe­cute the PlaceA­Clock method to place a new clock in the scenario.

metodo clock destroyed de gamecontrol para informar que un reloj ha sido destruido
Fig. 16: In Clock Destroyed we removed the maze piece con­tain­ing the watch from the list and placed a new watch.

AddSeconds Method of Timer

We need to define a pub­lic method with­in Timer that allows us to add a num­ber of sec­onds to the timer.

At the end of the script we make the dec­la­ra­tion of the AddSec­onds method, we will com­plete it at the end.

metodo add seconds de timer para agregar segundos a la cuenta regresiva
Fig. 17: In the Timer Script we are going to add a pub­lic method to add sec­onds to the timer.

Return­ing to the Game­Con­trol Script, in the Clock­Col­lect­ed method we make the call to the AddSec­onds method of timer, pass­ing as para­me­ter the whole timePerClock.

metodo clock collected de game control para informar que se ha recogido un reloj y se debe sumar segundos al timer
Fig. 18: In the Clock Col­lect­ed method we are going to add sec­onds to the countdown.

Now let's go to the EndGame method, where the Destroy lines are, let's run the Destroy­All method and cut the two Destroy instruc­tions that we had pre­vi­ous­ly placed in oth­er items.

metodo end game para realizar todas las acciones al finalizar una partida
Fig. 19: Let's go to the EndGame method, cut the destruc­tion instruc­tions and exe­cute the Destroy­All method.

We paste those two instruc­tions into the Destroy­All method and then find all the clocks on stage and destroy them using a fore­ach loop.

metodo destroy all para destruir todo lo que sea necesario al finalizar una partida en el juego del laberinto
Fig. 20: In Destroy­All we paste the pre­vi­ous­ly cut instruc­tions and remove all clocks from the stage.

Setup Clock Prefab

Now let's select the pre­fab­ri­cat­ed clock from the project fold­er and drag it to the sce­nario to set it up.

prefab de elemento colectable en unity, los relojes aparecen aleatoriamente en el escenario
Fig. 21: Select the pre­fab of the clock.

We cre­ate the Clock tag and assign it to the GameOb­ject of the clock.

creacion de tags en unity
Fig. 22: We cre­at­ed a new Tag called Clock.

asignacion de tags en unity desde la ventana inspector
Fig. 23: We assign the Clock tag to the pre­fab of the clock.

ventana inspector de un reloj que aparece en el escenario aleatoriamente en el juego del laberinto
Fig. 24: Clock with the assigned tag.

Then drag the Script Clock to its com­po­nents or use the Add­Com­po­nent but­ton. Then we intro­duce "Play­er" in the tag field (fig­ure 25).

gameobject colectable en unity
Fig. 25: Assign the Script Clock to the pre­fab of the clock and enter the player's Tag.

Let's go to GameOb­ject Con­trol and enter the new para­me­ters that we had pre­vi­ous­ly defined.

ventana inspector del game object control que se encarga de control el juego del laberinto, parametros para colocar elementos colectables en unity
Fig. 26: Select the Con­trol object and set the new para­me­ters in the inspector.

Now let's com­plete the AddSec­onds method of the Timer Script that we had pending.

Inside we will sim­ply increase the sec­onds, adjust the min­utes and exe­cute the Write­Timer method to update the values.

metodo add seconds de timer para agregar segundos a la cuenta regresiva
Fig. 27: Back to the Timer Script and com­plete the AddSec­onds method.

Programming error

At this point an error appeared in the con­sole say­ing that there is no ver­sion of the PlaceA­Clock method that does not have parameters.

error visualizado en consola de unity
Fig. 28: An error occurs say­ing that there is no method def­i­n­i­tion that does not con­tain parameters.

I go to line 184 of the Game­Con­trol Script where the error appeared, in effect we see in fig­ure 29 that the exe­cu­tion of the PlaceA­Clock method is done with­out parameters.

correccion de bug en script game control del juego del laberinto en unity
Fig. 29: I go to the instruc­tion where the error is located.

I define the inte­ger nPieces with the val­ue of the amount of ele­ments in the labyrinth parts list and enter this inte­ger as a method parameter.

correccion de bug en script game control del juego del laberinto en unity
Fig. 30: I define an inte­ger with the num­ber of labyrinth pieces and pass it as para­me­ter 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 sim­u­la­tion and searched the hier­ar­chy, I dis­cov­ered that they had appeared but were upside down, as shown in fig­ure 31.

bug en el que los elementos colectables en unity aparecen mirando boca abajo en el juego del laberinto
Fig. 31: When run­ning the game we find a bug, the clocks appear face down.

To cor­rect this bug I go to the method where a clock is placed on the stage and I look for the instruc­tion in which I make the Instan­ti­ate, instruc­tion 173 in fig­ure 32.

Instead of giv­ing the new GameOb­ject the rota­tion of the Quater­nion iden­ti­ty I'm going to give it the rota­tion that is defined in the pre­fab of the clock, which when placed on the stage appears cor­rect­ly oriented.

solucion del bug en el que los relojes aparecen mirando boca abajo en el juego del laberinto
Fig. 32: I go to the point where I place the clocks on the stage.

solucion del bug en el que los relojes aparecen mirando boca abajo en el juego del laberinto
Fig. 33: Instead of using Quaternion.Identity I use the rota­tion defined in Prefab.

Final Details and Test

When I tried the game, I noticed that there were few watch­es and that they gave up very lit­tle time when I picked them up.

In order to bal­ance the ele­ments cor­rect­ly it is nec­es­sary to make sev­er­al tests and see what works best, in addi­tion this can form part of a sys­tem of dif­fi­cul­ty in which a high dif­fi­cul­ty implies less fre­quent clocks that deliv­er lit­tle time when pick­ing them up.

ventana inspector del game object control que se encarga de control el juego del laberinto, parametros para colocar elementos colectables en unity
Fig. 34: I adjust the val­ues in Game­Con­trol to give me more time to col­lect them.

In fig­ure 35 we have two clocks in front of nos­tors and the timer marks approx­i­mate­ly one minute fifty, the fig­ure 36 was tak­en moments after grab­bing the two watch­es, we see that the Timer now marks a lit­tle more than two min­utes ten. This con­cludes the problem.

escena del juego del laberinto en el que hay dos relojes para recoger y obtener tiempo
Fig. 35: In the scene two clocks are observed in front of the char­ac­ter and the time indi­cates 1:47.

escena del juego del laberinto
Fig. 36: After pick­ing up both watch­es, the time is 2:13.

Conclusion

In this arti­cle we have seen how to ran­dom­ly place col­lec­tables in Uni­ty, these col­lec­tables were the clocks that when col­lect­ing them had to add time to the countdown.

The object Game­Con­trol is in charge of plac­ing them on the stage ran­dom­ly using the solu­tion cre­at­ed in the pre­vi­ous arti­cle to place the pedestal ran­dom­ly in a piece of the labyrinth.

To solve the prob­lem we have cre­at­ed a Script that will mod­el the behav­ior of the clock and will exchange mes­sages with oth­er Scripts to report events such as a self-destruc­tion or that the char­ac­ter has picked up the clock.

The effect of col­lec­table ele­ment we do it sim­ply exe­cut­ing appro­pri­ate actions when the char­ac­ter pass­es over them.

Scroll to Top
Secured By miniOrange