Как сделать раннер на юнити

Мобильная 3D игра на Unity3D менее чем за 90 часов

Этап-1: концепция

Как правило, начинающие разработчики, наступают на свои первые и самые значимые грабли уже на данном этапе, потому что перед тем, как приступить к созданию чего-либо, неплохо было бы оценить собственные возможности. Просто задайте себе вопрос: хватит ли у вас сил, времени и умений на создание проекта ААА класса? Ответ – нет! Отбросьте эту идею в долгий ящик, и не возвращайтесь к ней до тех пор, пока не реализуете чертову дюжину удачных проектов. К слову, под удачей мы подразумеваем количество установок от 500 тысяч, рейтинг свыше 3,5 по 5-ти бальной шкале и коммерческий успех. Для начала, займитесь более простыми, я бы даже сказал приземленными проектами, вроде аркад в стиле addictive games, сочетающих в себе все необходимые нами критерии «удачного» проекта.

Преимущества стиля addictive games:

Этап-2: создание наброска

Вот мы и подошли к самому главному этапу разработки, и пока с вашего лица еще не сошла разочаровывающая улыбка, позвольте вам напомнить, что набросок – это видение продукта. Создав его, вы фактический утверждаете техническое задание будущей игры, благодаря которому все дальнейшие шаманства и танцы будут исходить именно из этого задания. Степень проработки эскиза определять вам и только вам. В конце концов, этот эскиз вы создаете для себя, а не для галереи искусств. На данном этапе, я просто беру ручку и блокнот, после чего начинаю рисовать, изредка оставляя краткие комментарии и пояснения:

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Из наброска видно, что игра предназначена для мобильных платформ, и запускается она будет в портретном режиме. Геймплей также бесхитростен: задача игрока заключается в преодолении опасного машрута на предоставленном игрой автомобиле, попутно собирая кристаллы. За каждый собранный кристалл и удачно пройденный поворот, игрок получает вознаграждение в виде очков бонуса. Касание по экрану заставляет изменять направление движения автомобиля по осям X и Z.

Этап-3: создание прототипа

Имея под рукой подробный план действий, можно смело приступать к созданию «мокапа» или прототипа будущей игры. По сути, данный этап – начало работы с Unity, и начинать его следует с настройки окружения. Вот, как это настроено у меня:

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

В левой части экрана расположились редактор Scene и Game. Последний отображает то, как именно игра выглядит на устройствах. В правой части: панели Hierarchy и Inspector, а чуть ниже расположены панели Project и Console.

Этап-3.1: под капотом

Внимание! Ниже будет описан простейший код реализации игры, рассчитанный на новичков, и демонстрирующий то, насколько быстро и просто можно добиться результата в Unity. Финальный код игры реализован на более глубоких познаниях языка, включающий проблемы хранения данных, оптимизации и монетизации проекта, однако, по понятным причинам, в данной статье о них говориться не будет. Все скрипты мы будем писать на C#, а тем, кому это не интересно, предлагаю смело переходить к Этапу-4: визуальный дизайн

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Итак, сцена готова, но как придать персонажу движение? Для начала, произведем некоторые манипуляции с объектом Sphere, добавив в него такие компоненты как Rigidbody и только что созданный скрипт sphereBehavior. Не забудьте отключить галочку Use Gravity, так как на данном этапе он нам не понадобится.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Если вкратце, то компонент Rigidbody позволяет объекту ощутить на себе все прелести физического мира, таких как масса, гравитация, сила тяжести, ускорение и.т.д. Вот почему для нас он так важен! А теперь, чтобы заставить тело двигаться в нужном нам направлении, нам всего лишь нужно слегка изменить параметр velocity, но делать это мы будем при помощи кода. Давайте заставим сферу двигаться по оси Х, для этого внесём изменения в скрипт sphereBehavior:

В Unity, тела описывают своё положение и направление, посредством специальных векторов, хранящих значения по осям x, y и z. Изменяя эти значения, мы добиваемся необходимого нам направления или положения конкретного тела. Строка rb.velocity = new Vector3(speed, 0f,0f) задает новое направление телу по оси X, тем самым придавая нашей сфере нужное нам направление.

Если вы сделали всё в точности, как и я, то ваша сфера отправится в бесконечное путешествие по оси X, со скоростью speed.

Теперь давайте заставим нашу сферу изменять свое направление, при каждом клике левой клавиши мыши так, как это реализовано в игре ZIGZAG. Для этого мы вновь вернемся к коду sphereBehavior и изменим его следующим образом:

Условимся, что когда сфера движется по оси X, то это движение называется движением «вправо», а по оси Z – «влево». Таким образом мы легко можем описать направление нашего тела специальной булевой переменной isMovingRight.

Этот кусочек кода отслеживает нажатие левой клавиши мыши, и если данная клавиша все же была нажата, запускает функцию changeDirection(), с простой логикой: если на момент нажатия левой клавиши мыши, переменная isMovingRight имела значение true, то теперь она стала false и наоборот. Напомню, что булевая переменная позволяет нам ответить на один простой вопрос: истинно ли утверждение о том, что тело движется по оси X, или нет? Иными словами, нажатие на левую клавишу мыши постоянно изменяет значение isMovingRight, то на true(тело движется вправо), то на false(тело движется влево).

Альтернативно, функцию changeDirection() можно записать в одну строку:

И последнее, что необходимо сделать, это переписать метод направления движения с учетом переменной isMovingRight:

Если isMovingRight имеет значение true (если сфера действительно движется вправо), тогда значение velocity принимает новый вектор направления rb.velocity = new Vector3 (speed, 0f, 0f); Если isMovingRight имеет значение false, значит тело более не движется вправо, а значит пришло время изменить вектор направления на rb.velocity = new Vector3 (0f, 0f, speed);

Запустите игру, проделайте несколько кликов мыши, и если вы сделали все в точности, как и я, то увидите, как сфера начнет описывать зигзаги.

Круто? Конечно нет! Ведь сфера движется, а мы стоим на месте. Давайте доработаем игру так, чтобы мы могли двигаться вместе со сферой и не упускали её из виду. Для этого нам нужно создать скрипт cameraFollow и прикрепить его к объекту Main Camera:

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

А вот код скрипта cameraFollow:

Как же осуществить слежение за объектом? Для начала нам нужно рассчитать разницу смещения между объектами Camera и Sphere. Для этого достаточно вычесть от позиции камеры, координаты сферы, а полученную разницу сохранить в переменной offset. Но прежде, необходимо получить доступ к координатам сферы. Для этого нам необходима переменная player, представляющая собой простой GameObject. Так как наша сфера находится в постоянном движении, мы должны синхронизировать координаты камеры с координатами сферы, приплюсовав полученное ранее смещение. Осталось только указать в поле player наш объект слежения, и можно смело любоваться результатом. Просто перетащите объект Sphere в поле Player, скрипта cameraFollow, как это показано на картинке (Main Camera при этом должна оставаться выделенной):

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Теперь же, давайте подумаем над генерацией дороги, по которой могла бы двигаться наша сфера, ведь сейчас она в буквальном смысле парит в воздухе. Начнем с настройки объекта Cube, представляющий, по нашему мнению, участок пути.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Если в вашем списке нет тэга Ground, то его необходимо создать во вкладке Add Tag.

Следующее, что нам предстоит совершить, это создать в корне проекта специальную папку с названием Prefabs, и перетащить в нее наш Cube, прямо из инспектора. Если после этого, имя объекта Cube стало синего цвета, значит вы все сделали правильно.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Префабы – это особый тип объектов, позволяющий хранить GameObject, а также все его значения и свойства в одном месте. Префабы позволяют создавать бесконечное множество объекта, а любое его изменение немедленно отражаются на всех его копиях. Иными словами, теперь мы можем вызывать участок пути Cube, прямо из папки Prefabs, столько раз, сколько необходимо.

Теперь давайте создадим пустой GameObject, (щелчок правой кнопки мыши по Hierarchy) переименуем его в RoadContainer и прикрепим к нему только что созданный скрипт roadBehavior:

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити

А вот и сам код roadBehavior:

Что же тут на самом деле происходит? Как видите, у нас есть переменная, которая позже, вручную будет привязана к нашему префабу Cube, и есть объект Vector3, хранящий координаты последнего установленного префаба (сейчас значения равны нулю).

Этот участок кода выполняет следующее: до тех пор, пока i

Источник

Dimitrios Ilias Gkanatsios

Stories about Game Development, Azure, Docker, Kubernetes and more

Creating an infinite 3D runner game in Unity (like Temple Run, Subway Surfers), part 1

tl;dr: check the code here on GitHub and play the game here on a WebGL enabled browser

This is another blog post/tutorial in my Unity game development tutorials series, the first one being about a 3D game. Here, we’ll explore how to make a very special kind of game, an infinite 3D runner game. Since this post became somewhat big, it is split in two parts (check the second part here).

Chances are high that you have played an infinite 3D runner game at least once in the past years, when this genre became known and successful. These games have a 3rd person camera pointing at the main character who is running towards one direction in a 3D environment, while he tries to avoid various hazardous objects popping around that can kill him upon collision. This environment can be either a big path in which the character can change lanes like in normal traffic (such as in the game Subway Surfers) or can swipe left or right in various points to correctly follow the designated path (like in Temple Run).

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиSubway Surfers game Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиTemple Run game

This tutorial we’ve made contains two levels that feature both game mechanics. As you’ll see, these levels share some similarities but also have some notable differences. As usual, you can find the code here on GitHub and play the game here on a WebGL enabled browser.

Assets credits

Since this tutorial is a 3D game, I wouldn’t have something great to show without any 3D assets. Since I have no experience in 3D assets creation, I needed to find some premade ones. What other place to look for that than Unity’s Asset Store? The Asset Store is a wonderful place, where you can easily find low cost (even free) assets for your game. This tutorial would not be made possible if not for these great assets we used:

Game overview

Upon game launch, player can see a screen with two simple buttons. He can choose one of the two game levels, either the “rotated paths” level or the “straight paths” level.

In the “rotated paths” level, Max follows a narrow platform (“path”) till he reaches its end. At some point before this happens, the game engine randomly chooses where to place the next platform, either left, right, or straight ahead. The point where this next path will be placed is at the end of the current path. When Max reaches the current path’s end, player has to swipe in order to go left or right, or just continue on the main path. If player does not swipe in time, then Max may collide with the wall and die (the red walls, depicted in the picture below). When walking on the path, Max can pick the candy that appears in front of him to get some points to increase his score, he can (must!) jump to avoid obstacles and, of course, he can swipe left or right when the platform is about to rotate in order to follow the new path.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиRotated paths level

Important: You’ll see me refer to player’s input as ‘swipe’. As you’ll see below, this game has two input methods (either arrow keys or swipe in a touch screen). So, when we say ‘swipe’, this implies either arrow keys usage or regular swipe usage on a touch screen.

In the “straight paths” level, Max follows a wide platform and continuously moves at a straight direction. Player can swipe left or right to move sideways along imaginary lanes (like in normal traffic), while he can pick candy to increase his score. He also must avoid randomly popping obstacles either by moving on a different lane or by jumping over them. If Max falls into an obstacle, he dies and the game is over.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиStraight paths level

In both cases/levels, the game can theoretically continue indefinitely. Game is over when Max falls onto a red wall (rotated paths level) or collides with an obstacle (both levels). When this happens, player can tap the screen to restart the game. Finally, as you can easily see, score is increasing as Max continues to be alive and keep running.

Diving deep into the game

Onto our game code and Unity scene construction! We’ll start by explaining the code for the common classes used in the two levels and we’ll finish by examining each level in detail. During the following sections we’ll describe the classes used in the creation of the game.

Regarding the game Input

The developer can easily alternate between two input methods for the player to use. He can either activate input by mouse/keyboard (left, right and up arrow keys) or touch input, i.e. player dragging his finger on the screen and swiping left, right or up. Both input methods have been created as classes that implement a specific interface so the main game just checks for the input method result, without having knowledge of how the input is accomplished (a very simple example of the Inversion of Control principle). Since we’ve used the same (more or less) code in our 2048 game tutorial, we will not get into details here, but rather encourage you to check that blog post for more information.

Intro Level

Intro level is the first screen our player we’ll see upon launching the game.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиIntro level main screen

Intro level uses Unity UI controls, specifically two Buttons, to let the player pick the level he desires to play.

This level has only one script that contains two methods. Each one corresponds to one button click and transfers the player to the next level, utilizing Unity’s SceneManager API.

Constants.cs file

If you’ve read any of my other tutorials, you’ll definitely know that I love having a Constants.cs file in my project. This class usually contains static variables (variables I want to be visible in my entire project). Apart from the visibility part, this file saves us from hardcoding integers and (most importantly!) strings in our game scripts.

As you can easily see, this class contains some static helpful variables for our game.

GameState enum

As all games that respect themselves must do, we have to have a simple enumeration called GameState.

Our game state enumeration is a simple one, containing three states for our game, i.e. when the game has not started, when the game is being played and when Max has died.

TimeDestroyer

We need some game objects to be destroyed after a certain amount of time, in order to take some weight out of our RAM and CPU. For instance, there is no need for a path to be ‘alive’ on the game after Max has walked past it and it is no more visible on the player’s screen. A simple solution to this problem is to have this object destroyed after a certain amount of time, which is exactly what this class accomplishes.

The TimeDestroyer script is attached to various prefabs in our game, specifically to the candy, to the obstacles and to the paths. It will make the game object disappear after a certain period of time, provided Max is not dead. This, because we do not want the player to see items disappearing from the screen when Max has died, as this would be somewhat awkward for the player to see. Last but not least, the LifeTime public field determines how many seconds this game object will be alive for.

Obstacle

In order to make our game tough to beat, we place some obstacles on the path. Max has either to walk past by them (both levels) or jump over them (rotated paths level) at a precise timeframe in order to avoid them. If Max falls onto one of them, game is over. On the pictures below you can see the two models we use as obstacles as well as their components.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиThe 2 obstacle models – prefabs Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиBarrel model components

As you can see in the component pictures, each obstacle game object is a triggered rigidbody. Code is very simple, just one method that activates when Max collides with the obstacle. As already said, when this happens, Max dies and the game is over for our player.

RedBorder

The RedBorder is used in the “rotated paths” level. It is red because it is hot (yeah, we could find a better excuse :P) and will kill Max if he falls onto it. Max has to avoid them and follow the correct route to the next path (either left, right or straight ahead).

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиRedBorder prefab Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиRedBorder components

The RedBorder script is attached to the RedBorder game object. As already mentioned, when Max touches the red border, he is dead and the game is over.

Game Manager

GameManager script is a script that holds some basic properties, such as the game state and the, unfortunate for our player, “Die” method. Check the script code below:

GameManager script is a Singleton, which makes only one instance of it alive during the course of the game. This single instance is accessible by the static property called Instance. If you’re looking for a more detailed Singleton description, check here on Unity’s wiki.

Constuctor is declared protected, so that outer classes cannot instantiate a new GameManager (necessary for the Singleton implementation). GameManager has a GameState enumeration, a bool CanSwipe property that allows the game to accept swipes from the player (used only in the “rotated paths” level) and a public Die method that runs when Max falls into a red border, an obstacle or off the path. It changes the game state and makes the UI show relevant messages to Max’s death.

Random Material

My artistic skills are mediocre, at best. So, when I needed to give some color to my paths, I decided to select some random colors for the rectangle shapes on the path’s floor. This is what this class is used for.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиRotated path level, you can see the random color on each path piece. Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнити6 materials to colorize our paths

These materials are located in the Resources folder of our solution, so we use the following code to load them:

During Awake, it assigns a random material to the game object, making it have a random color.

Candy

Most games have a way to increase a player’s score in order to make the player happier, allow him to compete with others and enhance the game’s value with some “replayability”. In our game, we’ve selected to use some beautiful candy 3D objects (you love candy, don’t you?) that increase player’s score when Max runs onto them. Imagine that they work like bonus points.

Listed below are the candy models/prefabs and the components of candy_01 (which are similar to the other three).

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиThe four candy prefabs Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиCandy components

The Candy script continuously rotates the candy on the Y axis on to make it more visible to the user. It has a public ScorePoints variable that holds the points that this bonus is worth and is a triggered rigidbody. Upon collision with Max, the candy game object is destroyed and player is awarded with respective points, having the game’s score increased.

UIManager

Almost all games have a HUD (Heads-Up Display), i.e. some 2D text and/or images that is used to give some information about the game to the player. Here, we want to display some trivial information to the user, so we used something really simple (two text objects) with the help of Unity’s UI system.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиThe two UI Text objects showing game status and current score.

Code for the UI script is pretty trivial:

The UIManager script has placeholders for two UI Text game objects. First one is the text object displaying the score, whereas the second one displays game status. The class itself is a singleton and has some public methods to set the score and status text objects. It also has a private integer variable that holds player’s score which is modified by the respective public methods. Needless to say that the same script is used by both game levels.

Max is animated!

The Max model has some animations embedded (luckily for us!). You can see these when the model is imported into Unity, check below. From these animations we’ll use the idle, the run and the jump animations for our purposes.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиAnimations of the Max 3D model

We use Unity’s Mecanim animation system to animate Max. Mecanim allows us to create a state machine in which

In our game, we use two boolean variables to help us transition between animation states. Actually, it’s pretty simple: in the beginning of the game, Max is in the idle state. When game starts, Max begins to run, so we transition to the run state. When player swipes up on the screen (or presses the up arrow key) Max jumps, so we transition to the jump state. When Max touches the path again after the jump, he continues to run (you guessed correct, back to the run state). Below you can see some relevant images taken inside Unity editor.

Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиThe animation state machine for Max. On tle left you can see the two variables (jump and started) that trigger state change. Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиWhen idle, when started variable becomes true then we transition to the run state/animation. Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиWhen Max running, if jump variable becomes true, then we transition to the jump state/animation. Как сделать раннер на юнити. Смотреть фото Как сделать раннер на юнити. Смотреть картинку Как сделать раннер на юнити. Картинка про Как сделать раннер на юнити. Фото Как сделать раннер на юнитиRun model animation assigned to run state

OK, states are all good, but how are the two variables modified? This happens by getting a reference to Max’s animator controller object, more on later, when we discuss the movement scripts.

End of part 1

We finished part 1 of the tutorial, check part 2 here! As a reminder, you can find the code here on GitHub and play the game here on a WebGL enabled browser. Thanks for reading!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *