Pt. 1 Background and idea, Pt. 2 Player and level builder


As a child, I did not have my own computer, so I had to be content with an hour of playing VK games. I also got a smartphone relatively late, but I also had enough of those games that were in a push-button phone. As such, I was not a gamer, but it is quite possible to pass the time at recess.

Later, when they finally bought me a laptop, I was completely absorbed by Minecraft for 4 years. Probably this was the only game that I liked so much (and I still consider it the 1st of the best), since literally everything is possible there.

Then I slowly got tired of sitting in the cubic world without getting out and I moved away from it. Just at that time, computer science began at school. It’s not that the teacher was well-versed (it’s strong to confuse the power supply and the video card), but she was able to lay the foundations of Pascal. This showed me that it turns out that I can write programs and games quite easily, including if I learn a programming language, because it’s fast and easy! (how wrong I was…)

So I wanted to create a game and after a little reading I began to choose an engine. Naturally, my eyes fell on Unity. I can highlight in it such advantages as:

  1. Simplicity, because both the menu itself and the main C # language are quite easy to learn

  2. A huge number of articles, topics on forums and video tutorials on almost any problem. (For example, UE has noticeably fewer video tutorials in Russian)

  3. I am a student. Schoolchildren are strength. Strength is unity. Unity is Unity!

So, after a while, I got 5 several quarters in a row for a hastily created game. The game itself was very simple. The game had small square rooms and corridors connecting these rooms. The playing field was an array of these rooms connected by corridors (field size 16*16 rooms). There were monsters in some rooms. The monsters were different. Some are small and weak, but literally pressed against the wall by quantity and plugged to death. Some took out almost the entire health bar with 1 hit, but were slow and could not leave their room. The goal of this game is to collect 5 keys to open the desired room and drive the 1st monster there, which moves faster than the player and deals 99 damage (maximum health is 100). The player could die as long as he wanted. He was reborn in the 1st of 4 rooms, where monsters in different corners of the location cannot enter. The game itself was not even equipped with an exit button or settings, but for school computer science teachers, this was enough.

For those who are interested in what “It” looked like, here it is:

how i came up with the idea

So, I graduated from high school and entered the university. During this time, I started at least 3 more projects and made grandiose plans for AAA projects that would blow up the network. However, I still miss the stars from the sky and decided to release a game in the likeness of past giants such as Crossy Road and Geometry Dash. From the first I took the idea of ​​simplicity, and from the second I took the idea of ​​graphics with colors glowing in the dark. True, in the course of creation, a friend noticed that most of all the game resembles another classic – Doodle Jump.

To create this game, I decided to free up as much time as possible and postpone other projects. Now I felt that I had started something that I had to finish. Still, it’s wrong to be interested in creating games and not release one.

The essence of the game, as described above, is as simple as possible. You need to jump as high up as possible, but as the height increases, new types and combinations of platforms will appear. So that the player is not bored, it will be possible to change the images (Standard – “Water Ninja”. You can see it in the image) and the theme of the map itself. New skins and themes can be obtained using the “Randomizer” by paying 100 coins that you have collected on the map or received by completing missions.

The images themselves are divided into:

  • Standard. They are the most and the chance of them falling out is about 74%

  • Rare. There are fewer of them. The chance of getting one will be no more than 20%

  • Epic. Beautiful images, the chance to get which will be 5%

  • Legendary. The name speaks for itself. The chance of this happening is 1%.

  • Special. These are images of events or thematic. The chance of getting one in the randomizer is only 0.01%.

I will tell you more about each component and their implementation in the following articles, and now I sincerely thank everyone for taking their couple of minutes to this article. I hope I was able to put at least a little interest in you and will continue to be happy to share the experience of creating this game!

Part 2. Player and level builder

In the last part, I told how I came up with the idea and what this toy is like. In the same speech we will talk about the character movement system and the level collector.

Disclaimer: This article is not a guide and is not recommended for pro reading because of the danger of flying into the stratosphere in your chair.


First, let’s figure out what we generally want from the player:

  1. Gotta jump and fall

  2. Must move smoothly on horizontal surfaces

For a simple implementation of physics in Unity, components are provided Rigid body and character controller. The first is a physics engine object, and the second is a script that controls the object. Initially, I started making a character with Rigid bodybut already at the initial stages I ran into a problem when the character himself entered from the wall, stuck to everything in a row and in some cases moved in jerks, so it was decided to get rid of Rigid body in favor character controller.

I implemented gravity and movement in two methods:

AT GamingGravity() I assigned to a variable gravity Force meaning -50fif the character is not touching the ground and -1f, if applicable. This was enough to ensure a fairly rapid fall and prevent the object itself from getting off the ground. To check the contact with the ground, one of the functions of the Character Controller: [chController].isGrounded returns trueif the object touches the ground and false, if not. These values ​​have been multiplied by Time.deltatime.

In method CharacterMove() all other movement of the character was implemented. At the very beginning of the method, a variable of type Vector3 reset to zero [moveVector] = Vector3.zeroto not carry over values ​​from the method’s past work.

Next, the character is given the opportunity to jump if the player touches the ground and the left mouse button is pressed (On android works like a click). For the jump itself, assign gravity Force meaning 20f.

The next step is to give the player the ability to move left and right:

If the mouse position along the x-axis is less than the initial position, then a variable of type float assign a value: [move] = ((startMausPos – Input.mousePosition.x) / 30f) * sensitivitywhere sensitivity is the sensitivity variable, and 30f was selected by the test method, so that when sensitivity = 1 the player moved at the desired speed. Next, you need to check for the maximum speed: If our speed is less than the maximum, then we assign its negative value to the variable [moveVector].x, otherwise, assign a negative maximum speed value.

If the mouse position along the x-axis is less than the initial position, then when assigning a value to a variable [move] subtract the initial position from the current position, and the variable [moveVector].x we assign not negative, but initial values [move] and maximum speed.

As a final step, we assign [moveVector].y meaning gravity Force.

Both methods (GamingGravity() and CharacterMove()) is called in update and rejoice in the movement of our character.

Level generation

I prepared all the level prefabs in advance, so in the end I got a kind of prefab collector. Of the pluses, one can note the flexibility in the assembly: it is possible to choose which levels cannot be created after the current one, select the type of level and its complexity. Of the minuses, a heap in the code from which it hurts the eyes, the soul. the fifth point and, accordingly, the chair.

On the stage, I created a Spawner object and hung a script on it, which is responsible for the assembly itself.

At the beginning of the script is the structure Lvlswhich contains:

public GameObject thisLvl; – the level prefab itself,
public GameObject[] impossibleLvl; – all prefabs that cannot be placed after this level,
public GameObject posseblelvl; – a prefab that can definitely be placed. It’s for insurance purposes.

To make the levels more diverse, I divided them into 2 types and 2 difficulties: Y5 (its height is 5) and Y10 (its height is 10) and one and 2 complexity. For each type of each complexity, I created structure arrays Lvls. Also added a variable difficulty difficulty Factor with original meaning 0.

In order to generate not an infinite number of levels, but only a few steps forward, I gave the faucet the ability to move: if the player is less than 20 units lower than the faucet, then the faucet starts the level generation method, and itself moves up to the height of this level.

Now about the process of selecting a level.

When the player gets closer to the faucet by less than 20 units, the script starts to determine which level to create. Since there are fewer levels like Y5 and they add to the complexity of the game, the chance of them appearing is 30%, and the remaining 70% remains for Y10. With the help of randomness, a variable is created and 1 of the types is randomly selected. after choosing a variable responsible for the complexity (I have this difficulty Factor) value 1 is added. Assume type Y10 is selected.

Move to method SpawningY10()where we immediately kick off to another method by passing it a parameter ten (level height in Y10) to determine which level to choose. This additional method is called in all spawn methods and takes the desired height as input. It is needed for the convenience of reading the script and makes it possible to choose, for example, from various map images. Inside this method, we choose what complexity to generate the level. If the random variable (from 0 to 100) is greater than difficulty Factorthen the complexity oneif less, then 2. The selected prefab is returned to the method SpawningY10()After which it checks if this new level is in the array impossibleLvl from current. If there is, then we repeat the method call to select the level. If the script has made more than 50 repetitions and still selects impossible levels, then we generate an object for safety net, possible.

With the help of such a collector, you can flexibly customize the assembly of levels by type, complexity, and even change the images of the map.


In order not to drag the article into a huge tape, I will stop there for now. In the next part, I will tell you how I made platforms with traps, which stones I stepped on and what happened in the end.

Thank you all for taking a couple of minutes of your time for this article. See you later!

Similar Posts

Leave a Reply