Before we begin, I invite you to watch the following video that resolves this problem, make sure to activate the english subtitles.
Procedure
In the first video we are going to work on the input station, which consists of models for the “WASD” keys and mouse buttons.
The goal is to get them to change color when the corresponding entry is pressed.
En la jerarquía hay un GameObject llamado #1 Input. Este objeto tiene todos los elementos relacionados a la estación de entradas.
This GameObject is assigned the Read Input script, which will be responsible for reading the entries and performing actions on the elements of the station.
There’s no need to do anything in the hierarchy. Go to the folder “Scripts to Complete”, “Video 1 – Read Inputs” and open the script “ReadInput”.
Why should the code go in the Update method?
All scripts that extend their MonoBehaviour class behavior have an implicit Update method, which is automatically evaluated in each frame of our game.
As explained in the video, if our game runs at constant 60 fps, the Update method runs 60 times per second.
The reading of the Inputs is a random event, so we cannot determine when the player will press a button. For this reason, when we need to read the entries, we must do so in all frames.
How do we read the inputs?
Let us imagine that we can ask the computer in colloquial language about the state of the entries, what questions would we ask?
If the answer to these questions is yes, we will execute an appropriate action for each one.
We already have the idea, now we just have to ask these questions using a language that the computer understands.
Using the if sentence, we can ask questions whose answer is true or false.
Unity’s Input class handles the inputs, so we use their methods to solve the problem. We have the GetKey method for the keys and GetMouseButton for the mouse buttons, in the argument of these methods we indicate the key using the enum KeyCode and the mouse button using integers, as can be seen in figure 6.
Solution
In this way, we can ensure that the Input station fulfils its function.
Conclusion
As a first conclusion, I would like to mention how we went from thinking about the problem in colloquial language (figure 5) to writing it in C# language (figure 6). Thinking about the problems in this way is simpler, because we abstract ourselves from the programming language.
An intermediate step between this colloquial language and the C# code would be the pseudocode.
Reading Inputs is the way we know what the player wants to do, so we have to define what tickets we are going to offer and when we want to read them (for example perhaps we are not interested in reading the WASD tickets when we show a cinematic).
Input events are random, that’s why we must read them continuously using the Update method.
To avoid complications it is advisable to read the inputs in a single script.
There may be other types of inputs, such as a JoyStick or tactile entry. We must study Unity’s Input class to understand how to handle them.
Introduction
A vector is a mathematical tool that allows us to represent magnitudes in which not only the intensity (or modulus), but also the direction and direction in which they are applied are important.
The vectors are very useful in the development of games, they allow us to define directions for movement, do ray tracing, among other applications.
The simplest and perhaps the most everyday example I can think of is that of a force. Forces are vector magnitudes, not only does the amount of force applied matter, but also direction and meaning.
If, for example, we change the direction of the force we apply to an object, the object will probably move in the opposite direction.
Other examples of vector magnitudes can be torque, angular momentum, velocity. In electricity and magenithm we have the electric field at one point, the Poynting Vector.
Vectors in the plane and in space
For practical reasons we are going to look at the case of vectors in the plane and in space, i.e. vectors of two and three components respectively.
Mathematically
Usually a vector is identified by a letter with an arrow at the top.
There are different types of notations, one of them is to write the components of the vector in parentheses and separated with comma. In the plane we use two components and in the space three.
Graphic Representation
The value of the vector represents the final point of an arrow starting from the origin of coordinates (i.e. (0.0) in the plane and (0.0.0) in space), to the coordinate indicated by the vector. As illustrated in figure 2.
Characteristics of a vector
Components
The components are the actual values for each axis of the coordinate system.
In the plane a vector has two components, generally x and y, in space we need three components, in general they are called x, y and z.
Magnitude
The module, norm or magnitude of a vector tells us about the size of the vector, the magnitude or intensity it has, in other words is how much the vector measures from the origin to the final point.
To calculate the module, Pitagoras’ theorem is used on the right triangles formed by the vector with the coordinate axes. This sounds somewhat complicated but the formulas are simple, in figure 3 we see the calculation of the norm of a vector in the plane and in space. Formula with examples.
Orientation
The orientation of the vector in the plane or in space. This allows us to calculate angles with respect to coordinate axes using right triangles, sinuses and cosines.
Given a vector we can find a single line that contains it.
Here we begin to see the usefulness of knowing about vectors to program video games, with the vectors we can represent movements in a determined direction or calculate the trajectory of a projectile for example.
Sense
Given a direction for the vector, we said that there is only one line that contains it, however the vector could be pointing to one side or the other of the line. With meaning we solve this ambiguity.
To change the direction of a vector it is enough to multiply by -1 all its components.
Vector in mathematics vs Vector in programming
In programming there is also a type of data known as vectors, arrays or arrays. However, this refers to a programming structure in which we can order data of the same type and use them to solve algorithms.
We can model mathematical vectors using arrays, however arrays can contain strings of text for example.
Mathematical Vectors in Unity
In Unity there are several components that use vectors, the simplest of which is the Transform component that determines the position, rotation and scale of a GameObject in Unity.
For this it uses three three-dimensional vectors. In figure 4 we can see these vectors in the inspector. Unity gives the vector components the name x, y and z.
Other components such as Colliders use vectors to draw the Collider, define its position and size. In figure 5 we see an example of Collider in three dimensions in which three component vectors are used and in figure 6 an example of Collider 2D in which two component vectors are used.
In addition to the Unity components, in our Script we can create vectors to use in our algorithms.
The name of the object by which we refer to these vectors in a C# Script for Unity is Vector2 and Vector3. We can see some examples in figure 7.
Conclusion
Vectors in mathematics are a useful tool for representing trajectories and forces.
A vector has a module that determines its size, a direction that determines its orientation in space, and a sense within that direction.
Given a vector we can find a single line that contains it.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 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 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.
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.
Resolution
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.
Next we are going to create a new Script called Clock, which we will later assign to the prefabricated 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.
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.
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.
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.).
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
We paste those two instructions into the DestroyAll method and then find all the clocks on stage and destroy them using a foreach loop.
Setup Clock Prefab
Now let’s select the prefabricated clock from the project folder and drag it to the scenario to set it up.
We create the Clock tag and assign it to the GameObject of the clock.
Then drag the Script Clock to its components or use the AddComponent button. Then we introduce “Player” in the tag field (figure 25).
Let’s go to GameObject Control and enter the new parameters that we had previously defined.
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.
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.
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.
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.
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.
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.
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.
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.
Conclusion
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.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 🔻
In video 4 we use empty GameObjects to designate specific positions in which to place the character’s prefab.
In this case we are looking for a more complex solution, first we are going to choose one of the pieces that compose the labyrinth. The piece we choose will be a duplicate of one of the pieces shown in figure 3.
It is not enough just to choose the piece, we need to obtain a position within it and this position must be within a region in which you can walk. We see these regions in figure 4.
When analyzing the problem we see that we will have to make several random decisions and it would be desirable that the solution we propose is independent of the number of pieces that the labyrinth has. In other words, if we add more pieces from figure 4, they are automatically added to the selection system.
Strategy: Define Segments
Given one of the pieces in figure 4, we are able to draw one or two internal lines where the player can circulate within the piece.
Let’s consider the ends of these two lines. Figure 6 identifies four points that would be the ends of these two segments.
These points could be represented with Empty GameObjects as children of the piece.
In figure 7 we see these two segments drawn.
Then we could place the pedestal with the sword at any point of one of the segments.
First of all, let’s choose one of the two segments, let’s suppose segment B (figure 8) formed by empty GameObjects B1 and B2.
Then we’ll take a random point between the two empty GameObjects, figure 9.
Finally at that chosen point we will place the pedestal.
In the case of the pieces of the corridor and dead end that only have one direction, we will make coincide the points A and B, that way we will have two coincident segments, then we will be able to use the same solution that for the rest of the pieces.
Implementation of the strategy
We have worked out a plan to place the pedestal somewhere inside one of the pieces of the labyrinth. Now based on this we are going to solve the problem.
First in the hierarchy I’m going to separate the obstruction pieces from the others, because these pieces are not going to be considered in our solution.
In the figure 1 we see selected the pieces that we are going to use.
We need to find the references of these pieces in our code to be able to choose one of them. The simplest way to do this is to use a Tag.
I’m going to create a Tag called “SpawnPiece” and assign it to all the pieces selected in figure 12.
Next we create the Script “LabyrinthPiece” (labyrinth piece) that will be assigned to all the pieces selected in figure 12.
In the Script first we will define four GameObjects that will be points A1, A2, B1 and B2. We declare them as serializable fields so that they appear in the inspector and we can assign them manually.
We select any piece type Crossroads and assign the Script LabyrinthPiece. In figure 19 we see that in the inspector appear the fields for GameObjects.
Next we’re going to create the four empty GameObjects that we’ll call A1, A2, B1 and B2. In figure 20 we see created the first point. Note that it is defined as the son of an Empty GameObject called Spawn, which in turn is the son of the crossroads piece.
We are going to position these four objects according to figure 6, at the ends of the imaginary segments that represent the walkable area inside the piece.
We assign these objects to their respective fields in the inspector, within the LabyrinthPiece component.
Finally we apply the changes. This is very important because we are applying the changes on the Prefab of the crossroads, that is to say that all the crossroads of the labyrinth will now have their own objects A1, A2, B1 and B2 and will have assigned the component LabyrinthPiece, with their own points loaded in the fields.
We can check that by checking every crossroads in the hierarchy and checking that it has these points and the Script assigned to it.
What follows is to repeat the process for the other pieces. In figure 26 we see the T-shaped piece, this case is similar to the bifurcation only that one of the imaginary segments will have its end in the center of the piece.
In the corridor piece we create only points A1 and A2. In figure 28 we see that these points are also assigned in fields B1 and B2 respectively.
In the corner piece, figure 29, the imaginary segments will have two coincident points, we could create only three Empty GameObjects and one of them assign it for example to A2 and B1, but we chose to create the four points.
The case of the dead-end piece is the same as that of the aisle only with less distance.
In figure 31 we see that in points B1 and B2 we repeat points A.
Method for choosing a random position of a piece – Random.Range
In the Script LabyrinthPiece we are going to create a public method that will return a Vector3 that will indicate a random position of the piece.
The first instruction will be to declare a Vector3 called position which will be the one we return to at the end of the execution.
Let us remember that they are two imaginary segments formed one by points A1 and A2, another by points B1 and B2. So then let’s do an if to choose one segment or the other.
In the if argument we use Random.Value to generate a random number between 0-1 and check if this value is less than 0.5f. This means that we will have a 50% chance of choosing segment A and another 50% of choosing segment B.
To choose a random point of the imaginary segment formed by the points we use the Vector3.Lerp method, which will make a linear interpolation between two Vectors3 that we indicate.
The method receives three arguments, the first two are the Vector3 between which it will be interpolated and the third parameter is the interpolation point we are interested in.
To exemplify the interpolation function consider the following: if the third value of the Lerp method is 0 we will have a Vector3 equal to the first parameter indicated. If it is worth 1 we will have a Vector3 equal to the second parameter indicated. And if it is worth 0.5f we will have a Vector3 that will be located exactly in the central point between the two Vectors3 that we indicate as parameters.
In this way we use Random.Range to generate a Vector3 that will be in some position between the points indicated in the first two parameters of the Lerp method and we assign that vector to the Vector3 position that we had defined at the beginning.
In an if region we use the position of points A1 and A2. In the other if region we do exactly the same but with points B1 and B2.
Finally we return the Vector3 position.
All this explained is summarized in the 7 lines of the GetRandomPosition method in figure 32.
Now, this we did was for the Script LabyrinthPiece that is assigned to each piece of the labyrinth.
In the GameControl Script we are going to create a method that will place the pedestal in a random position in the labyrinth and make use of the public method of LabyrinthPiece.
We begin by defining the fields shown in figure 33 below the comment “//Video 9”. These are the fields and variables that we will use to solve the problem.
In the GameControl component in the inspector (assigned to GameObject Control), fill in the fields. In SpawnPieceTag type “SpawnPiece”.
In ObjectToFind we will assign the Prefab of the pedestal with the sword, which is the object to find.
In the minimum distance for the moment we write the value 75. Then we will see what this variable is used for.
It is not necessary that the LabyrinthPieces array appears in the inspector so I am going to remove the [SerializeField] selected in figure 37.
In the StartGame method we are going to find all the GameObjects of the hierarchy that have the Tag that we indicate in the inspector. Last instruction of the startGame method in figure 40.
Then we declare the PlaceObjectToFind method (figure 41) and call this method from the StartGame method (figure 42).
PlaceObjectToFind Method
What we will do with this method is to choose a random piece from the labyrinth, making sure that piece is far enough away from the player using the “minDistance” variable that we assigned 70 in the inspector. If the selected piece does not meet this requirement we will choose another piece again. This is taken care of by the While loop shown in figure 43.
Once we find a part that meets the requirements, we will place the pedestal at a random point inside. For this we use a version of the Instantiate method, which receives three parameters: The first is the object to be found stored in the “objectToFind” field, the second is the position that we will receive automatically from the labyrinth piece executing the GetRandomPosition method of the LabyrinthPiece component assigned to it. The third parameter is the rotation, here we will indicate: Quaternion.identity (a rotation identity).
It is important that we save the reference of this new object that we have created, we will do it in “objectToFindInstance” (last instruction in figure 43). This way when the game is over we can destroy this object manually.
In the EndGame method we destroy the instance of the object to be found, figure 44.
When you enter the game mode and press the Start button, everything seems to be working correctly. The pedestal with the sword appears in a random labyrinth position inside one of the pieces.
Place object in other regions
There are regions of the labyrinth that are outside the pieces, for example the one highlighted in figure 47. We might be interested in placing the object in a position belonging to this area.
How could we reuse what we have done?
To begin with we created an Empty GameObject and called it SpawnArea and placed it between the pieces of the labyrinth.
Then we created four empty GameObjects to represent points A1, A2, B1 and B2. We place these objects at the ends of the two imaginary segments of the area highlighted in green in Figure 49.
Then we create a Prefab along with the other pieces of the labyrinth (figure 51), because we may reuse this object by changing the internal points.
Then we assign the component LabyrinthPiece and place the internal points in the respective fields.
Do not forget to assign the Tag SpawnPiece in the inspector, otherwise these areas will not be considered when choosing a position for the pedestal. In my case, as can be seen in figure 53, I had not assigned it and I spent several minutes testing for the pedestal to appear in these areas.
Final Details
When I tried the game, I noticed that the door was quite large in relation to the character, so I made it a little smaller and applied the changes.
Another problem I detected was that there were pieces with the Tag SpawnPiece whose inner region was inaccessible to the player. In figure 55 you see one of these pieces, if the pedestal appears here, the player won’t be able to find it.
The solution to this is to select this piece and remove the Tag SpawnPiece, this way the piece will not be considered.
Conclusion
In this article we managed to place the pedestal in a random position within the labyrinth.
To do this we had to analyze the type of pieces that make up the labyrinth, establish certain rules and propose a strategy to solve our problem.
We used object-oriented programming thinking to create a flexible solution that fits all types of parts.
As usually happens, there is no single way to solve a problem. Another way to address this situation is to make a Navmesh Bake and take a point within these regions.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 🔻
To create a model of the labyrinth we are going to use the prefabricated ones that we created previously, we will place them in the hierarchy and we will begin to duplicate them and to arrange them in the space, as it is observed in the following figure.
Create terrain in Unity
To create a terrain in Unity we will use the GameObject “Terrain”, which will allow us to modify its relief and textures in a simple way using different brushes and parameters.
Download Files
First we download the next Zip file, extract the folders and take them to Unity.
The next thing we do is remove all the elements belonging to the scenario.
Terrain Component – Unity
As mentioned above we will use the Terrain component to create a mountainous relief for the terrain.
This component uses “Height Maps” or height maps to create reliefs, these maps are grayscale textures in which completely black areas are mapped with minimum height and white areas with maximum height (both heights configured in the parameters), the rest of the gray areas will have a height proportional to its color tone.
We can see this in the following image.
In the hierarchy right click > 3D Object > Terrain.
In the stage a white plane appears and in the inspector we can see that it has two components that define it, the component Terrain and a Collider type Terrain.
Terrain Component Setup
It is important that we first configure the basic parameters of the terrain, such as the dimension and the difference that will exist between the maximum and minimum height. Then we can modify these parameters but we will probably lose the design we had.
As shown in figure 9, click on the gear icon to go to the configuration. Then enter the parameters.
The only thing I’m going to change is the resolution of the land, which will be 1000 x 1000.
Texture Setup
We can paint the terrain using different sets of textures that will consist of Albedo and Normal maps. First we select all the normal maps we have, in the inspector we choose the type of texture as “Normal map” and apply the changes. We do this for all the normal maps we have.
Then select the terrain again and click on the brush icon, then on “Edit Textures…”, “Add Textures” (figures 13 and 14).
In the pop-up window we can select a texture that represents the Albedo in the RGB channels and its Alpha channel is mapped in the softness. Another texture for the surface Normals. We can also configure the size of the mosaic or TileSize using the fields “Size” and “Offset” that are observed in figure 15.
Click on Select and choose first the Albedo map and then the normal map.
We’ll do this for all the textures we’ll use to paint the terrain.
Figure 17 shows some values that work for TileSizes.
Once we set up all the textures, we should have them all available for use in the Textures in Inspector window, as shown in figure 18.
Making the labyrinth
First to keep things tidy I’m going to create an Empty GameObject that I call “Maze”, inside which will be all the prefabricated ones that I use to make the labyrinth.
Then I drag all the prefabs to the stage and start duplicating them and moving them to form the corridors.
To facilitate the positioning of the pieces we can use the orthographic view. In figure 20 at the top right we have what is called a “Gizmo” that shows the axes X in red and Z in blue. By clicking on these arrows we can change the view of the scene and if we click on the cube in the center we can alternate the view from Perspective to Orthographic.
In figures 20 and 21 we can see how this orthographic view is. The effect it produces is as if all the elements were compressed into one plane, so we do not observe the depth.
We go into game mode and go through the labyrinth to detect problems. In figure 5 you can see one of the badly placed doors.
Relief modeling
Then we’re going to start modeling the mountains. Select the GameObject Terrain from the hierarchy and in the inspector click on the first icon of the component (figure 27).
Then we select some pattern in the section “Brushes” that is observed in figure 28.
The next thing we do is paint in the editor and the terrain will gain height.
Another useful tool is the levelling tool (selected in figure 30).
This will allow us to establish a certain height and as we pass it over the terrain in the editor, the lower areas will begin to rise and the higher areas will descend, this is illustrated in figures 32 and 33.
After playing with the tools for a while, I ended up with something similar to figure 36.
The most important purpose of the relief is to cover the horizon and somehow provide guidance to the player.
Apply textures to the terrain
In the final phase of this article on how to create a terrain in Unity we will apply the textures configured above.
Select the brush tool in the inspector, a pattern and a texture.
Then in the editor we go around the terrain and paint.
We can alternate the textures and with this we can avoid that the ground looks monotonous with an only texture.
The mountains will have a base of earth and then we will be applying in different parts a rock texture
From time to time we go into game mode to see how the relief looks from inside the labyrinth.
Conclusion
We’ve seen how easily we can create a piece of land in Unity using the same tools that the engine provides us. We also apply different textures to give it diversity.
The exercise proposed in this article and video is very simple, but with enough time and practice we can build a number of reliefs.
This type of land has the limitation that caverns or caves cannot be built. For that we will have to superimpose another 3D model.
In addition we have created the labyrinth using the prefabricated ones configured in previous entries. Simply by making duplicates and moving in space.
We can make both simple and complex labyrinths and assemble a level selection system if we wish. The possibilities are unlimited.
Let’s bear in mind that this project is only a prototype, in order to achieve a better graphic quality it is necessary to build better 3D models and use a greater diversity of textures and higher quality. It would be nice to add decorative elements such as rubble or trees.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 article we are going to see how to program a timer in C#, the operation will be counting backwards from the initial values of minutes and seconds that we indicate and in addition the Timer will be in charge of updating the information in the user interface created in the video 5 of the series of the labyrinth. Here is the article in which we created the user interface, in short we created some elements for the Canvas, which will allow the user to start playing and see information about the game.
The prototype is a first-person game in which the stage is a maze. Inside the maze, there will be a hidden object that must be found before time runs out.
Now we’re about to solve the part where time runs out. In this article we’ll create a script that is going to work as a countdown timer.
The Timer will start the countdown from a value of minutes and seconds that we will indicate in the inspector, this means that every second of clock we must update the information.
The Script Timer will also modify the value of the Canvas text element (top of figure 1).
When the time count reaches zero, the Script Timer will execute the EndGame method of the GameControl Script, this way the game will end and we will return to the main menu.
Step by Step
We start by creating the Timer Script and open it in the editor. In order to access to the UI components, like on-screen texts and buttons, we need to include the UnityEngine.UI namespace at the top of the script (figure 3).
Fields
To make the countdown timer work we’ll need a couple variables.
In figure 4 you can see a “[SerializeField]” instruction above certain variables, this simply makes the variables and fields to appear in the inspector.
The two serialized integers (minutes and seconds) are the initial values of the countdown timer.
While the two private integers (m and s) will be used to keep track of time.
We also need a Text type object to have the reference of the Text component of the Canvas.
Select the “Control” object from the hierarchy and assign the Timer Script. We see in the inspector the serialized fields of the Script Timer: minutes, seconds and timerText.
Let’s write one minute and five seconds for the initial values of the countdown timer. Then take the Timer GameObject from the hierarchy (the one that contains the Text component, figure 6) and drag it to the timerText field.
In figure 7 we can see that in the timerText field a Text type component has been recognized.
Methods to implement
Having in mind how a Countdown timer works, some ideas of possible methods emerge. First for the Timer to start working we’ll create a method called StartTimer(). Then another method that runs at intervals of a second that is going to take care of incrementing the time value, we’ll call it UpdateTimer(). A third method to stop the Timer, that will be executed when it finishes counting, this will be StopTimer().
Finally, a method that modifies what is being shown in the user interface, this method will be called WriteTimer() and will take as parameters two integers for the minutes and seconds.
Note that the parameters required by this method have exactly the same name as the two integers previously defined, which are in charge of keeping track of the time.
This is done so on purpose to talk a little about contexts in programming, probably for later in another article.
Programming the functions of the countdown timer
UpdateTimer() Method
We have proposed some methods intuitively considering roughly the functioning of the Timer, now we must fill those methods with C# instructions that are the ones that will do the job.
The UpdateTimer method will take care of subtracting a second, checking if the time has not run out, and modifying the minutes accordingly. Finally, it will use the WriteTimer method, passing you the values of minutes and seconds. Figure 10 shows an example of how to implement this.
In the first instruction of the method we decrease by one unit the variable seconds, then we check if this variable is negative, i.e. if previously it was worth 0 and now it is worth -1.
If this happens we notice if the minutes variable is worth 0, if it is true this means that the time of the Timer is exhausted (I leave the comment //endGame in that region). If the minutes are not equal to zero, we decrease the minutes variable by one unit and make the seconds variable worth 59.
Finally we execute the WriteTimer method passing the variables m and s as parameters.
WriteTimer() Method
This method will take care of modifying the Text object that we had defined. Depending on whether the variable has a single digit (i.e. less than 10) or has two digits (greater than or equal to 10), we are going to execute the instructions seen in figure 11.
What is done is to concatenate a series of strings or text strings, in the case that s is less than 10, we concatenate a 0 in front of the seconds so that it conserves the format of two numbers.
There are other ways to do this such as setting a format for text strings, but in this way we take the opportunity to see how easily we can concatenate text using the sum operator.
StartTimer() Method
This method will perform the initialization of the Timer, that is, we take the minutes and seconds variables that appeared in the inspector with the initial values and assign them to the variables m and s that carry the count.
The method to write the values in the graphical interface is executed.
Finally we use the Invoke method, giving as parameters the string “updateTimer”, which is the name of the method and the second parameter is 1f that represents a second. This will make the updateTimer method run after one second.
We are going to add this same instruction at the end of the updateTimer method, this way the method will invoke itself every second. This can also be done using the InvokeRepeating method instead of Invoke.
Interactions between Scripts
The Timer is like a device that fulfills its function, we can configure it, put it to run and stop it. With this in mind, we are going to make the GameControl Script the one that controls the Timer, being able to start and stop it using its public methods.
First we are going to define a Timer type object to use in the GameControl Script.
Then in the Start method we find the Timer reference that is assigned to the same GameObject Control hierarchy (hierarchy in figure 6).
In figure 14 we see underlined, the statement of this object Timer and how we find the reference in the Start method.
Now the GameControl Script has the reference of the Script Timer instance, this means that you will be able to access its methods and public fields using the dot operator.
In GameControl’s StartGame method we’re going to make the Timer start working.
At the same time, we also want the Timer to have some way of telling the GameControl Script that time is up, so we also need the reference to the GameControl object within the Timer Script.
In figure 16 we see the declaration of this object and how the reference is found within the Start method.
For now we are going to make that when the time runs out the game ends and we return to the main menu, that is to say the same thing that would happen if we press the Escape key. This can be done by running GameControl’s EndGame method.
In previous videos we had declared it with private visibility, which implies this method can not be executed from an external context, for example the Script Timer.
So that we can execute it from the Timer Script we change to public visibility. See figures 17 and 18.
Now if, in the UpdateTimer region where we detected that the account reaches zero (we had left the //endGame comment), we execute the EndGame method of the GameControl Script and then the return sentence to finish the execution of the UpdateTimer method.
In the EndGame method of the GameControl Script we are going to stop the Timer, as can be seen in figure 20.
Why didn’t we make the UpdateTimer method stop the Timer when the count reaches zero?
It could have been done in many different ways, at the time I chose to do so bearing in mind that the Timer only serves the function of keeping track of time and warn when the time runs out, then the GameControl Script that uses the Timer decides what to do with it.
StopTimer() Method
In this method we will only cancel all invocations that may be pending, we could also reset the timer values to the initial values.
As an observation, in the code of figure 19, if the Timer reaches zero, the EndGame() method is executed and then the instruction return, which means that the program is forced to exit the current method, therefore updateTimer() will not be invoked again and the CancelInvoke() instruction would not be necessary.
But we could execute the EndGame method due to other reasons, for example pressing the Escape key or the player wins the game, in those cases it is necessary to cancel the UpdateTimer invocations.
Final tests
I’m going to make sure it works as expected, first I’m going to set 0 minutes 5 seconds as initial values and enter the game mode.
When entering the game mode the Timer starts with 5 seconds, makes the countdown and when it reaches 0 we see in figure 24 that returns to the main menu.
Now we verify that the format of two numbers for seconds is respected and that the minutes are correctly decremented when the seconds go from zero to 59. We start the Timer with 10 minutes 5 seconds and enter the game mode.
We observe that the format of two digits is respected for the seconds and in addition the minutes are decremented correctly. The exercise is finished.
Conclusion
We have managed to complete our Timer in C#, which serves the function of keeping track of time, displaying it in the user interface and when the time runs out notify the GameControl Script to decide what to do.
This timer could have been implemented in several different ways, the Invoke method was chosen in this case, because I considered a quite simple alternative.
We saw how easily we can modify a text component of the Canvas as long as we have its reference, so we can use this for other things like scoring, information messages, etc..
We began to introduce little by little the concept of objects, how each has a specific function and have references to other objects to make use of their methods and public parameters. This is an extremely interesting and useful topic for creating object-oriented solutions.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 article we will program the logic of the user interface created in video 5 of the labyrinth series. If you did not read the previous article, in summary we created a user interface in Unity, which will have the minimum functionality for the user to interact with the game.
In the previous article we designed a simple user interface so that the user can control the fundamental aspects of our game, such as starting the game, knowing how much time he has left, etc…
At this point we are going to use the GameControl Script to manage the user interface. In the following chapters we will delegate this responsibility to a new Script.
To summarize the elements of the user interface we have two screens, one for the main menu which contains only one button that serves to start the game. The second screen is for the game and has a text element that will show the amount of time left to finish the game.
Resolution
In the GameControl Script we define three serialized GameObjects, one for the camera that is active in the main menu, another for the menu interface and another for the game interface.
The three GameObjects defined are highlighted in Figure 1.
In figure 2 we can see that these new fields appear in the inspector.
We take the objects created in the previous video and drag them to the fields in the inspector. These objects are the camera, the GameObject MainMenu and the GameObject Game.
StartGame and EndGame methods
We are going to define two methods, one is going to be called “startGame” and the other “endGame”. The startGame method will have the function of doing everything necessary for the game to start, i.e. setting the timer to zero, placing the character’s prefab, placing the pedestal in a random position on the stage and so on. Keep in mind that these actions will probably be defined in other methods.
In the endGame method we remove all objects from the scenario, go to the main menu and so on.
In the methods we are going to activate and deactivate the corresponding elements, as can be seen in figure 6.
Let’s go to the hierarchy and select the “Start” button, to observe its properties in the inspector.
In the Button component there is a field called OnClick(), let’s click on the plus sign in the lower right corner, in figure 8 the cursor is over this button.
This will allow us to run public methods within the GameObject components we assign.
In the field that appears we are going to place the GameObject Control.
Ahora utilizando el menú desplegable, podemos acceder a las componentes y sus métodos.
Como se trata del botón Start, estamos buscando el método StartGame que hemos definido en el Script GameControl, en la figura 12 podemos observar los atributos y métodos públicos del Script GameControl y vemos que StartGame no se encuentra entre ellos.
This is because we use private visibility in the definition.
To solve the problem, we changed the method to public visibility, as shown in Figure 14.
Ahora podemos elegir que se ejecute este método cuando se haga clic en el botón Start.
I arrange the camera a little so that the small scene of the doors is seen and I enter the game mode to test the operation of the button.
Bug fixing
When entering game mode, the character appears on one of the doors randomly, but for some reason the controls don’t work properly, the character drags on the floor and the camera turns in a strange direction.
The Debugging process can be a bit tortuous, luckily we have tools to analyze the flow of the program, discover the parts of the code that work properly, see the values of the variables and so on to detect the problem and be able to correct it.
Without going into details, because I honestly don’t remember how I discovered the bug, the problem had to do with the hierarchy structure between GameObjects and the inherited transformation of the parent GameObject.
To correct the problem in the instruction to instantiate the character, within the “placePlayerRandomly” method, change the rotation from local to global, as seen in figures 20 and 21.
This corrects the problem and we can use the start button to start the game.
Final details
When you enter the game mode, the first-person controller prefab captures the cursor, places it in the center of the screen, and hides it.
This is a problem because when we return to the main menu when the game is over we can’t click on the buttons. So the solution is to unlock the cursor and make it visible at the end of the game, i.e. in the endGame() method.
To find out how to do this let’s analyze the MouseLook Script that uses the controller in the first person. In figure 23 we can see this Script along with its route to get to it.
Fatal Error
When trying to open MouseLook the editor fails and must be closed losing all unsaved changes! It is important to save at all times, the CTRL+S access is very useful.
On the second attempt we were able to access the script. We are looking for an instruction related to the Cursor.
We see that in lines 93 and 94 of figure 26 there are a couple of instructions that seem to be the indicated ones so we copy them.
Then we go to the GameControl Script and paste these instructions at the end of the endGame method that will run when the time runs out.
End the game
We are also going to give the user the possibility to end the game whenever he wants by using the Escape key.
We do this with the GetKeyDown method of the Input class.
In the first video of Unity’s fundamental series, I explain how to read keyboard and mouse entries, plus the difference between the different methods, there is also an article about the video on this page.
Conclusion
In the article we discuss how to program the interaction between the user interface elements and the GameControl Script.
In the case of the button the functionality is already programmed for it to execute methods of the Scripts, but we must make sure that these methods have public visibility.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 article we are going to analyze in detail the video 5 of the labyrinth series, in this video we create a simple interface with the minimum functionality so that the user can interact with the game.
This article covers the design of the graphical interface, the programming of the operation is done in the following article.
The user interface of our game will allow the player to configure parameters such as resolution, volume, load and save games, start playing, see your score and so on.
In our case we will focus on making a graphical interface with the minimum functionality we need for the project, which is first a “Main Menu” where the game starts and from there we can start the game.
The second thing we need is a graphical interface that is shown while we are playing, for the moment we want to visualize the countdown.
User interface functionality
What we’re going to do is create a Canvas type GameObject that is a basic element in the GUI and then two empty GameObjects that will contain all the elements of the main menu and the game.
When the game starts the graphical interface of the main menu will be active, which will only show us a button to start the game.
Pressing the button will turn off the graphical interface of the main menu and turn on the game which shows the remaining time to complete the mission.
When the game is over, we’ll turn off the game’s graphical interface and turn on the main menu interface again.
This way we don’t need a second separate scene for the game and we can solve everything in the same scene.
Procedure
Before we start making the graphical interface we will create a prefabricated object of the door to be able to replicate easily. We took the scene as it was at the end of the previous video (figure 1) and eliminated three doors and three points of appearance.
We take the point of appearance we have left and make it the son of the door.
Then we take the GameObject Gate from the hierarchy and drag it to the Prefabs folder of our project, with this we create a prefab that we can place as many times as necessary in our game.
We are going to create a camera that will be initially active for when we show the graphical interface of the main menu.
This camera will be turned off when the game starts so that it doesn’t conflict with the camera included in the character’s prefab.
User interface design
Now we begin to create the necessary elements for the graphical interface. First a Canvas where the elements will be placed.
Como se dijo en la introducción, creamos dos Empty GameObjects para que contengan los elementos de cada pantalla.
Vamos a nombrar a estos objetos “MainMenu” y “Game” para identificarlos fácilmente, como se observa en la figura 9.
Right-click on the GameObject “Main Menu” to create a button.
To see our graphical interface, in the tab “Game” we will select an aspect ratio 16:9.
Inside the button we have like son a GameObject type text, we are going to select it to modify it in the inspector.
Type “Start Game” in the text field shown in figure 13 on the right.
Using the basic tools we can position the button on the screen.
When entering the game mode we see that the button has an animation when you press it, but of course it still does not perform any action.
Let’s give the button the name “StartButton” to easily identify it in the hierarchy.
The next thing we do is create a text type GameObject, this time as a child of the “Game” object.
In the inspector we write any value with the time format, only to visualize it on screen. Later we will modify the text using C# code.
In addition to writing the text we can do other actions such as center, change the size of the font, font type, color and so on.
We choose a font size that fits the button well.
With the GameObject “Game” selected, at the top of the inspector we have a button that allows you to enable and disable it (figure 21), this makes it show or not in the graphical interface.
We will use this property from the C# script to program the behavior of the GUI.
Adaptation to different screen resolutions
How to make our game look good in any screen resolution is not a minor problem.
There are several ways to approach this issue, for example we could create a different user interface for each resolution, then using a c# script we could detect what type of resolution the device has and show the appropriate graphical interface.
In this video we use a component that is assigned to the Canvas and is called “Canvas Scaler”, canvas climber.
This component will make the graphical interface bigger or smaller depending on the screen resolution. For the moment this will help us.
Display the “UI Scale Mode” menu which by default is in “Constant Pixel Size” and select the “Scale With Screen Size” option.
Then we set a reference resolution, in my case I’m going to use 1920×1080, as shown in figure 24.
We must now adjust all the elements so that they look good for that reference resolution.
Adjusting the canvas scaler is something that would have been better to do from the beginning, but in this labyrinth series we’re showing all the elements we count on to make a game in Unity, it didn’t make sense to show the canvas scaler before showing the canvas and its elements first.
Once we have adjusted the elements to the new reference resolution, we can observe the behavior of the Canvas Scaler, selecting Free Aspect for the aspect ratio, using the drop-down menu we use in figure 1.
Then making the window wider or narrower we observe in figures 28 and 29 that the button becomes proportionally larger or smaller.
The last thing we do is create a new resolution for the game window. FullHD 1920×1080.
This resolution is only for viewing in the editor, it has nothing to do with the resolution that the executable game will have.
Conclusion
In this article we have reviewed the key points to create a simple graphical user interface, i.e. the minimum necessary elements that the player needs to see to use the game.
The basic element of the graphical interface in Unity is the Canvas, inside the other elements will be placed.
The “Canvas Scaler” provides us with a simple solution for adapting the graphical interface to different resolutions.
As the project has not yet advanced much, the game still does not have more functionality than placing the character on the stage. Later on we’ll have to include more elements in the interface and probably create more screens.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 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.
We began by assembling with the prefabricated a scene like the one shown in figure 1.
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.
We are going to call this object “SpawnPoint”.
In the inspector we can choose an icon to better visualize the GameObject in the scene.
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.
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.
We select again the GameObject “SpawnPoint” from the hierarchy and in the Tag menu we select the Tag “SpawnPoint” that we just created.
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.
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.
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.
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.
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.
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.
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”.
With the new GameObject selected, we drag the GameControl Script into the inspector to add it as a component.
Figure 18 shows that the script has been added as a component to the Empty GameObject Control.
Another way to accomplish this is by using the Add Component button and searching for the GameControl Script.
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.
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).
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.
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.
We take the Prefab FPSController and drag it to the new field in the inspector, as shown in figure 24.
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.
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.
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.
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.
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.
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.
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).
Let’s create some copies of this GameObject with CTRL-D and go back into game mode.
Now we can see that the array is of size 4 and contains all the references of the GameObjects.
We put a SpawnPoint in every 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.
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.
In figures 40 and 41 we see two tests of the game in which a different point of appearance has been chosen.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 article we’ll look at the different types of Colliders and how to apply them to our 3D models, as well as how they interact with the RigidBody component.
We started by clearing the scene of the GameObjects that were left in the previous video. Let’s leave the pedestal with the sword and the clock, to be able to analyze the different types of Colliders.
The sword and the pedestal are two separate objects grouped under the same father, so we can select the sword and remove it from the pedestal (figures 2 and 3).
In addition we will create a cube and a sphere by right clicking on the hierarchy and using the 3D Object menu. We arrange the objects so that they look like in figure 4.
With the cube selected, we observe its properties in the inspector. By default it comes with several properties included, among them there is a Box Collider component.
Components can be removed by using the small gear at the top right of a component and clicking Remove Component, as shown in Figure 6.
In the following figure we see that the Box Collider component has been removed.
We can add new components to our GameObjects by clicking on the “Add Component” button, when we do so a window is displayed with all the components and has a search bar. If we type “Collider” in the search bar we can see the different types of Collider we can add to our GameObject.
Of course there are Colliders that are more appropriate than others for a particular GameObject, this will depend on the geometry of the GameObject and the use we are going to give it.
Let’s deactivate the MeshRenderer component of the cube to better observe the Collider, the components usually bring a small box to the left of their name to activate or deactivate them.
In figure 9 we see that the Box Collider is represented as a Cube defined by green edges. Because the GameObject is a cube, this type of Collider fits perfectly into its geometry.
Now let’s select in the hierarchy the GameObject sphere and see its properties in the inspector.
This time he’s assigned a type of spherical Collider.
Again we deactivate the Mesh Renderer component to observe the Collider (figure 11). Again, as it is a spherical GameObject the type of spherical Collider fits perfectly to its geometry.
Let’s see what happens with the sword, select it in the hierarchy and observe its properties in the inspector. Unlike the two previous GameObjects, the sword is not assigned a Collider by default, we must assign one manually as shown in Figure 8.
First we assign a Box Collider. In this case as shown in figure 13, we see that a box appears with the minimum volume necessary to fully contain the GameObject sword.
Then we tried a kind of spherical Collider. As shown in Figure 14, the Collider is a sphere with the minimum radius such that the sphere completely contains the GameObject sword.
Now let’s add a Mesh Collider, this type of Collider will use the geometry of the object. Figure 15 shows its properties in the inspector.
We deactivate the Mesh Renderer to observe the Collider and what we see is that it has the exact shape of the sword, the Collider coincides with the geometric mesh of triangles.
Of course this brings more complexity in the calculations of interactions with this type of Collider, so we have to decide if it is necessary to use it, or with a Box Collider is not enough. Everything will depend on the purpose.
Next we’ll select the GameObject clock in the hierarchy and apply a Mesh Collider but this time we’ll click on the “Convex” box that is seen in the properties of the Collider in Figure 18.
In figure 19 we observe that now the Collider type partially respects the geometry of the object. This type of Collider also involves more calculations, but not as much as it would be in the previous case, is as if we had a low poly model of the GameObject.
It also has other advantages such as being able to use it in Trigger mode.
For now we saw three types of Colliders: Box Collider, Sphere Collider and Mesh Collider, the latter can be used in Convex mode, which simplifies the geometry of the Collider.
Physical behavior of the Colliders.
The Colliders behave like barriers that can’t be crossed. In other words, if our character has a Collider and tries to go through a GameObject assigned to a Collider (such as a cube or a clock), he won’t be able to do it. Unless this Collider is in Trigger mode.
Figure 21 shows that the character is standing on the clock, the spherical Collider prevents it from falling.
Now we are going to place the sphere suspended in the air over the cube (the latter was scaled).
With the sphere selected click on Add Component and within the Physics category select the RigidBody component.
Figure 24 shows the parameters of the RigidBody component. We can assign a mass, activate or deactivate gravity and modify other parameters related to the physics of an object.
When entering the game mode we see that the sphere falls as if by gravity and collides with the corner of the cube (actually the collision is with the Collider).
The RigidBody component gives physical behaviour to the sphere.
Add Colliders to the labyrinth pieces
We are going to place one by one all the prefabricated ones created in the previous video and configuring their Colliders so that the player can’t go through the walls.
First the closed alley piece. We take the Prefab from the project folder and drag it to the scene or to the hierarchy. Then in the inspector click on the Add Component button and choose the Box Collider component.
We see in figure 28 that the Collider completely covers the GameObject, which will not allow us to walk inside it.
Figure 29 shows that in the game mode the character can only advance to the border of the Box Collider. This type of Collider is not suitable for this piece.
We have an alternative, if we click on the button “Edit Collider” of the Box Collider (figure 30), we will be able to modify the position of its faces.
This way we can make the Box Collider enclose a part of the object.
Then adding more Colliders and repeating the previous process for the rest of the geometry of the object, we would be able to represent with sufficient precision the border of the object.
Figure 33 shows that the superposition of the three Box Colliders covers the entire geometry of the piece and allows the player to move around inside.
The above works for us, but let’s eliminate all the Box Colliders and add a Mesh Collider instead, in this case the wall geometry and quite simple.
Something very important when we are dealing with Prefabs is to apply the changes we are making, for that we use the Apply button located at the top of the inspector (if we have the Prefab selected).
Figure 36 shows the model of the portal with an assigned Mesh Collider component.
It is not justified to use a Mesh Collider for this model, taking into account the use that we are going to give it, let’s put better a Box Collider and apply the changes to the Prefab.
The same for the pedestal model, with a Box Collider we get enough.
The clocks are going to be collectible objects, that is to say when the player passes over them, these will disappear and will give more time of game.
Bearing in mind the use that we are going to give them, we are going to use a spherical Collider, increasing a little the radius as it is observed in figure 39.
Then let’s activate the “Is Trigger” option of the Sphere Collider component. This will ensure that the Collider does not hinder the player and allows him to detect when he enters the spherical region.
Conclusion
In this article we look at different types of Colliders and what each may be appropriate for.
Everything depends on the purpose that we have for the GameObject, for example in the pieces of the labyrinth we use Mesh Collider because we need to be able to walk through the inner regions of the model. On the other hand in the clocks we use a spherical Collider because it is a piece that the character will be able to grasp.
Colliders interact with each other and are very important when RigidBody components come into play, which give GameObject physical behaviour.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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 article we are going to import assets, i.e. 3D models and textures, add them to the Unity engine and configure them so that they are ready to start working on stage. We are going to create GameObjects prefabricated that we can then reuse and we are going to modify the sky that comes by default, replacing it with a Skybox where we will apply the textures that were downloaded from Asset Store in the previous video.
The first thing we are going to do is to download the necessary files for the project. You can do it in the following link.
3D Models and Textures
Within these files we will find 3D models for the labyrinth walls, a pedestal, a sword and a clock. Each model has its own textures.
Select the folders and drag them to the appropriate folder in Unity.
I do this first by selecting the files, then clicking to drag them (a ghost icon appears indicating the amount of files being dragged) and then pressing the ALT-TAB combination to change the window, this does not make the selection lose, that’s why we can drop the files into the Unity folder.
If there are problems to do this you can minimize the Unity window or use the Unity import options.
Then we do the same with 3D models. You have to take into account the folders we created in the previous video in order to organize ourselves.
Modify scenario
Now let’s put all the 3D models on the stage to start shaping the labyrinth.
First we remove all the elements of the scenario except the floor. In the previous video we had placed them all as children of an Empty GameObject called Scenario.
The next step is to take the 3D model called ScenarioElements that we import and drag it into the scene or hierarchy. This will place all the pieces of the labyrinth on the stage.
In the previous video we had made the floor brown. Now we are going to apply textures so we make it white again, otherwise our texture will have a brown tint.
Apply textures to the floor
Now we are going to use the textures that come inside the zip that can be downloaded at the beginning of the article.
We start with the floor, inside the folder we have three textures.
The Base Color texture is used to give color to the material. Metallic determines the behavior of the material in front of light and the normal texture also determines how the light bounces off the material, but it is used to add geometric details that appear to have a high density of polygons in 3D models.
Place textures in the slots of the material
We add the textures in the inspector, to see the material in the inspector we have two options: we can select the material directly from the project folder or selecting a 3D model of the world that has it assigned.
Figure 8 shows that the textures are assigned in the slots of the material.
Albedo slot determines the color of the material, there we place the texture Base Color. The metallic texture in the slot metallic and the normal texture in the slot Normal map. For the latter we must define that texture as a normal map, there are two ways to do this, but Unity gives us the option in the same place, as shown in Figure 8 appears a sign that says that this texture is not defined as a normal map and we have a button to fix it. We click on Fix Now.
Tiling of textures
The upper left corner of Figure 8 shows a portion of the soil. Notice that the floor looks blurry unlike what it should look like (a lawn floor with daisies).
This happens because the texture is expanded to occupy the entire plane, to change this we must make it repeat more times in the geometry. This is done with the Tiling parameter of the material, in my case (because of the size of the plane) the values 100 for X and 100 for Y work.
What is going to happen is that the same texture is made smaller and placed one after the other. In figure 10 you can see the lawn with daisies. Notice how in the lower part of the image the ground looks good, but as we move away the pattern of the texture becomes more evident, it is obvious that it is the same texture that repeats itself.
We are using a “Seamless” texture, that is to say a texture that when you put it one after the other (in the four sides) fit perfectly and you don’t notice a line of rupture. Even though the texture is very good, we can’t avoid the repetition pattern from a distance. To avoid this we have to use more textures, place objects that interrupt the pattern and so on.
Figure 10 also shows that the floor reflects a lot of light, as if it were made of glass or something similar. To correct this we decrease the Smoothness value, making the material reflect less light.
Extract materials from 3D models
In previous versions, when we imported a file with an FBX extension, the materials that could be defined automatically appeared along with the models. This has changed and I think it makes sense that we have to manually extract the materials, so we can have better control and avoid having many copies of the same material.
There are two ways to extract the material, at least in the version at the time of recording the video.
In this case we click on the imported model and in the inspector we go to the materials tab and click on: “Extract from prefab”.
A window appears to select the location of the extracted materials, if you want we can create a folder for the new materials.
The new materials appear in the selected folder.
Apply textures to new 3D models
The next step is to do the same thing we did with the floor material, we are going to go material by material adding the textures to the respective slots.
There is a problem that arises when we have to do this type of tasks and is that when we select something in the hierarchy or folder of the project, the inspector shows us information about that selection. In our case it would be good that the inspector is blocked showing the material we are configuring.
For this there is the small padlock that you can see in the upper right corner of the inspector tab. Clicking on it blocks what the inspector shows and we can navigate freely through the project folders without losing sight of our material. Beware that this can also be a problem, sometimes we forget the locked inspector and we don’t know why we can’t see information about what we select.
Another alternative for this type of tasks is to modify the Unity layout for our benefit, that is to say to open more tabs of the project and to lock them so that each one shows a thing.
Figure 16 shows that one of my project windows shows the materials, the other shows the textures and the inspector shows the selected material. This makes the process of adding many textures to the materials faster.
Creation of Prefabs
Once we have configured all the materials, the next step is to create the “Prefabs” that is to say GameObjects prefabricated that later we will be able to instantiate during the design or in time of execution of the game. For example, later on we will make the clocks appear randomly on the stage. In order to achieve that we need to have a GameObject prefabricated from which clones will be created.
To create a prefabricated GameObject we simply take it from the hierarchy and drag it to any folder in our project, as shown in figures 18 and 19.
After that the Prefab appears in the folder, as a thumbnail that shows its appearance and name. From there we can take it and drag it to the scene to create all the copies we need, as can be seen in figure 20.
We repeat this process for each individual piece of the labyrinth, pedestal and portals.
Define a new Skybox
Now let’s modify the standard sky of the scene. We will use the files downloaded from the Asset Store of the previous video, doing this was an optional step, so if you have the files no problem, we can keep moving forward.
First we create a new Material, we call it “Sky” and we select it to visualize its properties in the inspector.
Then we click on the Shader drop-down menu that by default has “Standard Shader” selected, instead we choose the Shader “6 Sided Skybox”. This will completely change the properties of the material in the inspector, now you see an inspector like the one in figure 23.
We will assign the textures of the Skybox package downloaded from the Asset Store to the corresponding Skybox slot.
Then go to the menu Window > Lighting > Settings to open the lighting configuration.
A window opens like the one shown in figure 26, which I place next to the inspector so that he is not floating.
Click on the icon of the circle with the “Skybox Material” point (on which the cursor is in figure 26) and in the window that appears we choose the Skybox that we have just configured (figure 27).
Immediately we see how the default heaven is replaced by a new sky of a cloudy sunset. With the appropriate images we can create a personalized sky for our project.
Adjust lighting
Figure 28 shows that the light is too pale, i.e. it does not look like the light you would see in a sunset. To correct this we select the light source in the hierarchy to see its properties in the inspector (an inspector similar to the one seen in figure 33 is observed).
In the inspector we select a color according to the tone of the sky and we adjust the intensity to taste.
Then we modify the rotation of the light source to match the position of the sun in the Skybox.
At this point of the video I make a folder to place the prefabricated ones belonging to the stage and others for the objects. Again I emphasize the organization of the project.
Finally it occurs to me to add a second light source that points directly down and does not produce shadows, that way the scene does not look so dark.
I select the light source from the hierarchy and press CTRL+D to duplicate it, then I orient it perpendicular to the ground.
In the inspector I adjust the parameters and in “Shadow Type” I select the option “No Shadows”, as it is observed in the figure 33. With this we finish the video 2 of the series My First Game in Unity.
Conclusion
In this video we have worked quite a bit on the aspect. We added 3D models and textures, so we learned a little more about the materials. In the case of imported 3D models, we must manually extract the materials that can bring or place new materials, this part is very connected with the 3D design of the piece, ie the materials defined in our 3D design software will appear in Unity, we may have the opportunity to delve deeper into this issue later.
We saw that we can create prefabricated GameObjects that are in the hierarchy. These prefabricated can be placed in the world easily, at the time of editing or at the time of running the game.
We modify the sky that comes by default in the scene, instead we create a Skybox type material in which we place textures to represent the six sides of the “sky box”, this behaves as if we were inside a giant cube whose horizon is very far away.
Finally, we improved the illumination of the scene a little, correcting the color and adding another light source that adds intensity but does not produce shadows.
Updated information about this project
This article belongs to a series that consist on making a first person game about finding objects inside a maze. It’s one of my very first series from the channel. Now I reworked this project and you can download it to import in your own Unity project. Some day I will make a new series about this project, subscribe to my channel to see all the fresh content about Blender, Unity and programming.
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
This is the beginning of the Labyrinth series, in which we’ll create a simple prototype of a first-person game in which the stage will be a labyrinth, while we see all the tools that Unity has to create games.
This series is ideal for those who do not have experience with Unity as it shows a little of everything and without going into detail, the purpose is rather to observe the entire development process to get a general idea.
When you run Unity or Unity HUB, a window appears in which you can create new projects, open them and access the tutorials.
We will create a new 3D project, give it a name and choose a location on the disk. Everything else is optional. When everything is ready we create the project
We give it a name and select the 3D template.
The first thing we’re going to do is create a new scene. In this version of Unity, by default we create the scene “SampleScene.unity”, as seen in the header of the program in Figure 2.
To create a new scene click on File > Save Scene As…
We give it a name and keep it. When you do it, you can see in the header the name of the new scene.
Each scene has its own design independent of the others. For example we can use one scene for the main menu and another for the game.
It’s all going to depend on how we want to structure the game.
Creating folders
It’s important to set up an organization system for our Unity game files from the beginning, because as we go along we’re creating more Scripts, importing more files and things get cluttered easily.
All project files are located in the “Project” window, inside a folder called “Assets”. This folder can be found in the directory we defined for the project.
As can be seen in figure 4, right-clicking displays a menu with different options, go to the “Create” option and choose “Folder”.
We create as many folders as necessary to organize ourselves, this part is personal.
Import Packages
To start making a game in Unity is not necessary to create everything from scratch, we can use existing libraries to start working on an idea. Next we’ll import Unity Packages from the Standard Assets library and the Asset Store.
Standard Assets – Unity
In the version of Unity that I had at the time of recording the video, you could import the Standard Assets packages, a library offered by Unity that has different prefabrications, effects and scripts that are useful to start with.
Right-clicking on the folder we have the option “Import Package” where we can choose a package that we have downloaded using the option “Custom Package” or we can choose a package from Standard Assets.
If you do not see all the packages as shown in Figure 5, you have the option to download them from the Asset Store, but you must have a Unity account to do so. We’ll talk about that later.
In this case I will import from Standard Assets the packages “Characters”, “ParticleSystems” and “Utility”.
With the package “Characters” we will be able to place in the stage a prefabricated one that has implemented a control in first person.
ParticleSystems brings some interesting effects to use, such as fire and smoke.
Utility brings some useful scripts like a frames per second (fps) counter.
Asset Store – Unity
Unity’s store contains an infinity of Assets, some of them paid and others free.
To access the shop we use the Unity Asset Store tab, if it is not open, go to Windows > Asset Store or use the direct access Ctrl+9. As shown in figure 6.
To use the store we must log into our account (we can do it from Unity). Then using the home screen or the search bar we can explore the content.
In order to see how Asset Store is used we are going to download two packages. The first is called “SkyBox” and the second “FastMobileBloom”, we use the search bar to find them, in figures 7 and 8 you can see the miniatures of the packages.
To add them to our project we enter the package and put “Download”, at the end of the download we have the option “Import”.
Project hierarchy
Within each scene all the elements of the game will be defined, that is to say a scenario, objects that are part of the world, invisible objects that serve for the logic of the game, graphical interface, etc. All these elements are known as GameObjects and will be listed in the hierarchy of our project.
As you can see in figure 10, when creating a new scene, we have two GameObjects that come by default. A camera and a directional light.
Let’s delete the camera and start adding objects to the scenario.
By right clicking on the hierarchy we have the option to add different GameObjects, e.g. empty objects, primitives, lights, etc.
I’m going to set up a simple stage with a floor plan and some buckets and cylinders.
As we add more objects to the scenario the hierarchy grows. It’s also recommended to have a good organization from the beginning, placing appropriate names and using Empty GameObjects to group the objects.
Note figures 14 and 15. In the first one you can see that both cylinders are contained by the cube, as they are slightly to the right and the cube has an arrow to unfold and collapse the contents. In figure 15, on the other hand, it is observed that they are at the same level, so to speak.
This represents the kinship that exists between GameObjects. In figure 14 it is said that the cube is the father GameObject and both cylinders are children. This implies that the cylinders are going to be affected by certain changes that apply to the parent. For example if we deactivate the cube, both cylinders will also be deactivated.
The same applies to the transformation component, for example. The position of the cylinders is measured with respect to their parent, so if we move the parent, the cylinders move together.
Materials
To apply colors and textures on the objects of the world the materials are used. Let’s create some to see how they work. Right click on a project folder then Create > Material, as shown in figure 16.
The material is visualized as a sphere in which are applied the properties of the material we must assign it a name, as always maintain the order from the first moment benefits us in the long term.
The materials have several parameters that define it, in our case we will simply modify the color by clicking on the box to the right of “Albedo”. When doing so, a color palette appears where we can choose the color or write its hexadecimal code.
To apply a material we simply drag it over the desired object.
Lighting
Let’s select the directional light from the hierarchy or in the scene window.
Directional light is a source of light such as the sun, i.e. situated in infinity and sending all its parallel rays. For this reason moving the source or making it larger does not affect the illumination of the scene, but changing the rotation if it does. We see it in the direction of the shadows.
Create a ladder with primitives
Let’s do this little exercise to see the elements of Unity’s toolbar, particularly the tools that will allow us to modify the Transform component of GameObjects. We started by creating a cube in the hierarchy.
The tools move, rotate and scale are shown in figure 22 in positions 2, 3 and 4 respectively and are quickly accessed using the “W”, “E” and “R” keys (respectively).
If we press the R key with the cube selected, we can scale it using the “Gizmo” of the three axes, as shown in figure 23.
We scale it in two directions to give it the appearance of a step.
We apply a material to it and with the W key we can place the step on the stage.
We can easily duplicate the object using the shortcut CTRL+D and with the W key raise it a little and move it backwards.
We can repeat this process with several selected steps.
Let’s create an Empty GameObject and call it “Scenario”.
Then we select all the objects and drag them to this new object to group them. In this way we can collapse the whole content and the hierarchy is more orderly, as shown in figure 30.
First-Person Controller
The reason why we previously removed the camera is because we are going to place the prefabricated “FPSController” from Standard Assets on the scene and it already has a built-in camera. This prefab is located in the directory Standard Assets > Characters > FirstPersonCharacter > Prefabs.
We take it to the scene and put it where we like.
Bugs
We are already able to do some tests, in the top center we have three buttons.
The Play button is used to start running the game. The second button pauses the game but does not end it. The third button is used to advance a single frame in the game.
Pressing the Play button displays an error sign saying that all errors must be fixed before you can enter game mode.
This is a problem that we are going to encounter very often, especially at the beginning and it is usually very frustrating, even more so if we are learning to program.
To get information about what is happening we have the “Console” window. If it is not open, you can find it in the “Window” menu.
In figure 34 we see a large number of warnings but this does not affect the operation of the game, are suggestions for optimizing the code, warnings for use of obsolete code and so on. If only we had warnings we could enter the game mode without problem.
Figure 35 is a screenshot after clicking the “Clear” button, this clears the warnings and lets you see the errors that cannot be overlooked in order to enter the game mode. These are shown with a Red sign.
There is not much information about the error but it is enough for us to understand that there is a file that is not found. If we look at the address we see that it is related to the Standard Assets package and we see that its address begins with “Assets > Standard Assets > …”. In the video we made a folder called “External Packages” and inside it we put the Standard Assets package.
Everything seems to indicate that there is some process that is looking for Standard Assets files but inside the Assets folder, not the External Packages folder, so I move the Standard Assets folder to the Assets folder and the error is fixed. Now if we are able to enter the game mode.
Testing the game at Unity
The prefab FPS Controller works like a standard first-person game. Move forward, backward, sideways with WASD keys or arrows. Jump with space bar, with Shift you can run. With the mouse you can control the view and it has the sound of steps. It’s a good starting point to start forming an idea.
Build the project
Now we will generate a standalone version of the project, ie a set of folders and executable file that can run on our operating system without having the Unity engine open.
Go to the File tab and click on Build Settings to configure the compilation parameters.
We get the window illustrated in figure 39, there we can select the target platform.
If you look at the top is where the game scenes are listed. At that time we don’t have any scenes added to the compilation.
By clicking on the Add Open Scenes button we are going to add the scene we were working on throughout the video. As you can see in figure 40.
Now all that’s left is to click on Build And Run and choose the folder where to place the generated files. At the end of the compilation process the game runs and a window appears in which we can select the resolution and quality. Press the Play! button and the game starts.
Conclusion
In this article we saw the first steps in starting a game at Unity. We put emphasis on organization, which will benefit us in the long run in development.
We saw the scenes of Unity, each scene is a world apart and contains a certain amount of elements or GameObjects that are listed in the hierarchy of the project.
We import files from both the Standard Assets library and the Asset Store. At the beginning the most important thing is to try to give form to the ideas that we have, for this the assets of the bookstores facilitate the things to us.
We saw something about the parentship that exists between GameObjects and how changes applied to a parent object also impact their child objects.
We create materials that give color and texture to objects.
The directional light source serves us to illuminate a scene as the sun would, the shadows will be projected according to the rotation that this light source has.
We made a simple ladder using the primitives that can be created with Unity and applying transformations to them, that is to say changes of scale, rotation and position.
We place the Standard Assets prefabricated “FPSController” which is a first person control. Quickly we already have a character that can go around the stage, run and jump.
In the process there were bugs that we had to fix in order to get into game mode. Debugging errors is a difficult task when we start programming, but with practice we make fewer mistakes and it’s easier to correct them.
Finally we made an executable compilation from the operating system. There are a lot of platforms to which we can export our game in Unity. In principle we are going to export to Windows and Android.
Introduction
This time I wanted to share a little experiment I did using Blender, Unity and Arduino. The simulation of an industrial process using 3D models made in Blender and making a scene in Unity.
Here in the Alto Valle of Patagonia fruit growing is practiced and as I work doing industrial automation I have the opportunity to observe how the packing sheds work and the treatment of the fruit.
The industrial process I try to simulate is a fruit grinding line. The fruit arrives through a water circuit to a fruit elevator that lifts the fruit to a sorting table, where people manually discard the bad fruit. Then the fruit continues its ascent to a mill where it’s transformed into pulp and deposited in a tank. This is where the simulation comes in.
Motivation
The idea of this experiment combining Unity and Arduino arose because I needed an idea for the final work of a subject of my career. The subject is PLC (programmable logic controllers).
I wanted to take advantage of everything I’ve learned from programming and 3D design, designing a computer simulation to test the programs we load into the PLC.
Description of the experiment
The idea is to use an Arduino Mega board to control the simulation in Unity. This is done using RS-232 communication. The Arduino board is inside a 3D printed box with a pair of Switches on the lid.
With the Arduino Mega you read the status of the switches and with this information you can create a word that is then sent via RS-232. The physical connection is made with the Arduino’s USB port.
In Unity the messages of the COM port are read.
The video shows that there are synchronization problems. This is because the COM port reading is done in the Update method of a class that inherits MonoBehaviour. An alternative to this is to use a different Thread to do the reading.
Conclusion
We haven’t decided yet what we’re going to do for the final work, however, this idea of an Arduino-Unity hybrid project is very interesting to me and I’ll probably make a series of videos for the channel. I think it might be fun.
Introduction
Creating the 3D model of a face can be a challenging task, especially when we’re just getting started in the 3D world. In this article we will see an easy and practical way to make a 3D face with a well-achieved geometry in Blender, but the technique can be applied in any 3d design software.
Timelapse of the modeling process of a 3D face
In the following video I use this process to make the 3D model of a Venetian mask. The textures were made using Substance Painter.
Topology is the discipline that studies objects and their geometric properties. In 3D models it refers to the set of vertices, edges and faces and their interrelation.
It’s very important that our 3D models have a good topology, that way the modifiers, proportional deformation, texture painting and other functions will have better results.
We achieve this by using 4 vertex faces (quads) and creating edge loops that fit the natural curves of the object we want to model. In the figure 1 we see those faces and how they are distributed in the 3d model.
If we use this kind of images as reference for our modeling procces we will achieve a 3D model of a face with a correct topology.
Reuse of the 3D model for a character
Marittie is a chibi character I made from a drawing my girlfriend made some time ago.
At the time, I had a year’s experience with Blender and was not yet familiar with the concept of topology. However, I managed to make a model and at that time I liked it very much.
The topology of course was not good. The model had a very high number of polygons, triangles, quads and n-gons, very badly optimized.
The animation was of course difficult to achieve. There were irregularities that were difficult to correct.
As time went by I learned to improve the geometry and it was time to remake the 3D model.
I had made the 3D model of the Venetian mask, so I thought why not use this 3D model as a starting point for my character design?
I made a copy of the mask and started applying proportional deformations. As the topology of the face was good, it was easy to transform the Venetian mask into Marittie’s new face.
Conclusion
It is important to achieve a good topology in our 3D models, because that means we can apply transformations to that mesh and it will respond appropriately.
The improved topology of the new model makes animation easier. The proportional deformation tool has better results and also the seam marking and UV unwrapping will be easier.
I wanted to share a project I did long before I started programming and the world of video games. It’s a computer cabinet made in mdf.
History
I had been making things in mdf, such as sets of chess and boxes that my girlfriend had decorated with decoupage, I liked quite and had ease. One day I was in chemistry class in the university and I showed a friend the little jobs I had done. He was interested and told me that he needed a temporary wooden box to cover his computer because he had not yet got a cabinet and his computer covered it with a cardboard box.
Figure 1 shows a structure for the motherboard and power supply that he made.
So the idea was to make a box containing that to prevent it from getting dusty.
Design of the MDF PC case
My friend made a design that seemed convenient for ventilation and from that I made a 3D design using SolidWorks (at that time I didn’t know Blender), that was my first approach with 3D modeling without counting that when I was a kid I made maps for Counter Strike using 3D Entity.
With the 3D design we were able to make some renders and adjust it until it became as my friend wanted. From that 3D design I made a plan of 6 views for the cuts of the pieces (I believe that by that time I had also made technical drawing in the university).
Taking as base the plans, I drew the six pieces on a plate of mdf of 5 mm of thickness, in this part the measures were taken well so that everything is to square.
I made all the holes in the internal cuts so that the sheet of the jigsaw enters.
I made the simple cuts using a hand jigsaw and the precise cuts with a bench jigsaw.
The cuts were made to measure, only not so straight because they were made by hand.
Figure 8 shows that the structure was already taking shape.
I glued the three pieces using glue and then applied a press so that the structure is very firm, then the pressing tools are observed.
Notice how the red metal press (a press itself) is in charge of keeping Monopoly’s box armed, so the structure didn’t collapse under its own weight.
For the disk bays we made a three-storey structure, in the following figure the idea for the design is shown.
The piece was also built with 5 mm mdf and a layer of red acrylic paint.
Then we started to think about the decoration of the box, because it had to have even a coat of paint. At that time I didn’t know as much about computer components and brands as I do now, however I proposed some designs that he liked.
The Republic of Gamers logo for an MSI board, I know.
We had bought some meat pies to eat and it was getting late.
Here you can see that I’m putting the finishing touches. Our mdf cabinet was almost finished.
We screwed the coolers in place, placed the structure with the motherboard, the fountain, the disks inside and finally the two pieces of acrylic that went into grooves. This was the final result
Conclusion
We managed to finish the mdf cabinet and my friend had a small box to house his computer. It was temporary until he finally got a PC cabinet.
In my opinion the dimensions were quite exaggerated, but my friend was worried (and rightly so) about refrigeration. In a metal cabinet the heat is partly dissipated by the thermal conductivity. In addition it provides protection to the circuits against electromagnetic noise.
However, if we take into account the fact that I used to cover the computer with a cardboard box, the mdf cabinet was a small improvement.
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Cookie settingsACCEPT
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are as essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.