Independent Game Development with Unity Game Engine
Independent Game Development with Unity Game Engine
Niko Jylhä
Master’s thesis December 2018 Degree Programme in Information Technology
ABSTRACT
Tampereen ammattikorkeakoulu Tampere University of Applied Sciences Degree Programme in Information Technology
Niko Jylhä
Independent Game Development with Unity Game Engine
Master’s thesis 62 pages, appendices 0 pages December 2018
"As far back as I can remember, I always wanted to be a gangster" is the opening line of the movie Goodfellas by Martin Scorsese, 1990 and as my opinion it’s one of the greatest in movie history. For me as a person that could be translated to "As far back as I can remember, I always wanted to be a game developer". When me and my brother got Commodore 64 back in a day for Christmas present it wasn’t enough to just play the games I wanted to learn how to make those space ships to fly and monsters to move.
But what does it mean to be a game developer? And to be more specific a “independent” one? How easy it is to start creating games? Is it possible to make money with games when there are thousands of games around?
Goal of this thesis is to share some light on those questions.
Theory part will focus on questions like, what “Independent game developer” means? What do you have to consider when creating games? How many independently created games are there and what kind of tools to create games?
Hands on part will focus on studying Unity game tool. Goal is to implement level of game called Tapper and to study basic concepts of game, moving things around, like player and enemies and collision detection.
Key words: independent, game development, unity 3d, steam, xbox, playstation
3
TABLE OF CONTENTS
1 Introduction ...... 6 2 Independent game development ...... 8 2.1 What is independent game development?...... 8 2.2 Indie game releases ...... 8 2.2.1 Steam Spy - PC ...... 8 2.2.2 Xbox 360, Xbox One and Playstation 4 ...... 9 2.3 How to become independent game developer ...... 10 2.3.1 Game design ...... 10 2.3.2 Level design ...... 12 2.3.3 Marketing ...... 14 3 Game Development Tools ...... 16 3.1 Microsoft XNA Game Studio/MonoGame ...... 16 3.2 GameMaker: Studio ...... 16 3.3 Adventure Game Studio ...... 16 4 Unity – Game Engine ...... 17 4.1.1 Learning the Unity ...... 17 4.1.2 Unity Asset store ...... 19 5 Tapper game ...... 21 6 2D Game Development with Unity ...... 22 6.1 Creating the 2D project ...... 22 6.1.1 Creating the scene ...... 24 6.1.2 Scene background ...... 25 6.1.3 Automatic scaling...... 26 6.2 Player object ...... 27 6.2.1 Player movement points ...... 28 6.2.2 Canvas ...... 29 6.2.3 Moving the player character...... 31 6.3 Enemy (aka customer) objects ...... 37 6.3.1 Enemy objects ...... 37 6.3.2 Spawning the enemies ...... 38 6.3.3 Moving the enemies ...... 41 6.4 Collision system ...... 43 6.5 Serving the drinks ...... 48 6.6 Ending the game ...... 53 6.6.1 Restart game button...... 53
4
6.6.2 Collision event to stop enemy spawning and to show Restart button ...... 55 7 Final words ...... 60 REFERENCIES ...... 62
5
LIST OF ABBREVIATIONS
XBLA Xbox Live Arcade – Microsoft’s game download service for Xbox 360. Steam Video game distribution channel owned by Valve Corpora- tion. NES Nintendo Entertainment System AAA or triple A “In the video game industry, AAA (pronounced "triple A") is a classification term used for games with the highest develop- ment budgets and levels of promotion. A title considered to be AAA is therefore expected to be a high quality game and to be among the year's bestsellers.” (Wikipedia) Apple App Store Apple video game distribution channel for IOS platforms iPh- one and iPad. Google Play Googles video game distribution channel for Android devices.
6
1 Introduction
Minecraft, Legend of Grimrock, World of Goo, Limbo, Fez, Super Meat Boy, Hotline Miami and Braid, just some of the names of the independent game development success stories. They all have been developed by individuals or small group of people in a way called indie game development.
Independent game development is a way for a person or group people to independently create games usually with small budgets. Now days game development tools like Unity and digital distribution channels like Steam offer developers’ easy way to start developing games. But starting is just the beginning the journey.
Purpose of this thesis is to study the what is indie game development and to learn how to create games using Unity Game Engine.
Objectives are: • to learn what independent game development means • popularity of indie games • what you have to consider when creating games • what game development tools are there to create your game • what distribution channels are there to publish your game • to learn how easy or hard it is to use Unity tool • implement level of Tapper game with Unity
Motivation for this thesis is the authors passion for video games and hopes of some day to publish his own game.
What is left out in this thesis is the actual publishing of the game. This side would be interesting to study in the future.
This thesis is presented in seven (7) chapters: • Chapter 1, introduction to this work. • Chapter 2, explains what independent game development is, shares some light about the popularity of indie games and explains some things you need to consider when creating games, like game design and marketing.
7
• Chapter 3, introduces to some of the game development tools out there. • Chapter 4, focuses on Unity Game Engine that was used in the “hands-on” part of this thesis. • Chapter 5, explains the Tapper game. • Chapter 6, is the hands-on part, where level of Tapper game is created with Unity tool. • Chapter 7, final chapter, talks about how things went, summary of goals set for this thesis and were they achieved.
8
2 Independent game development
2.1 What is independent game development?
Independent game development is a process where game is developed by a small group of people or even by one individual. Game budget is usually small, and it doesn’t neces- sarily have any publishers. Games are usually not released on physical copies, instead distribution channel for the game is usually digital portal like XBLA (Xbox Live Arcade), Steam, Apple App Store, Android Market Place, Nintendo eShop or some other similar channel.
2.2 Indie game releases How many indie games are there? Well, you could say that a “lot”. Exact figure is impos- sible to say because there isn’t just one list that lists them all. Although indie games are important strategy for companies like Nintendo, Sony and Microsoft they don’t reveal lists of the indie games and line of “independent” is not always so black and white. For PC platform Steam Spy web site is probably best place to look for information but for other platforms like Xbox it’s a bit harder. Just to get the idea of popularity of creating indie games let’s have a look at two platforms PC and Microsoft Xbox using Steam Spy statistics and googling.
2.2.1 Steam Spy - PC Steam by Valve Corporation was released in 2003 for PC. Steam is digital distribution platform for video games [https://en.wikipedia.org/wiki/Steam_(software)]. Steam Spy [steamspy.com] is a web site that collects sales statistics about the games sold in Steam. From 2003 to 2017 there are almost nineteen thousand games released and around twelve thousand of them are categorized as “indie” games. Although listed games don’t cover those games that are not sold in Steam (For example, those that are sold only in Xbox Live are not listed) it gives good picture about the popularity of creating indie games. In the early years, from 2003 to 2006 only around twenty indie games were released. It seems that after the 2010 number of releases slowly start to grow until 2013 it jumps to three hundred and the next year 2014 it’s almost thousand games. Between 2015 to 2017 its over ten thousand games.
9
Steam Spy - Indie games released per year 6000
5000 5120
4000
3377 3000
2000 2109
1000 984
183 300 0 100 2003 2005 2007 2009 2011 2013 2015 2017
FIGURE 1 - Steam PC indie game releases
2.2.2 Xbox 360, Xbox One and Playstation 4
Finding statistics for Xbox 360, Xbox One and Playstation 4 indie games is a bit harder. “Googling” revealed two sources that were quite useful. For Xbox 360 good place was Xbox market place US [https://marketplace.xbox.com/en-US/Games/XboxIndieGames] although I notice that some flaws in this list; some indie titles like Braid and Super Meat Boy were missing and listed games start from 2008 even though Xbox Live Arcade (XBLA) service was released for Xbox 360 late 2005. Xbox 360 has been a very popular platform for indie developers, one reason for that is the Microsoft has been supporting indie game development right from start of the Xbox 360 with its Xbox Live Arcade service. Microsoft has closed its indie program so it’s no longer possible to develop indie games for Xbox 360 and developers have moved to newer platforms [https://www.eurogamer.net/articles/2017-09-08-xbox-live-indie- games-officially-closes-29th-september]. For Xbox one and Playstation 4 I found a web site that lists released indie games. [https://www.finder.com.au/gaming/the-complete-list-of-indie-games-on-xbox-one, https://www.finder.com.au/gaming/playstation-4-indie-games]. Interesting comparison
10 between these systems is to notice that first years they have quite similar number of re- leases but in the year 2017 Playstation 4 took a jump of almost two hundred games above Xbox One.
XBox 360/One and Playstation 4 indie games released per year 900 834 800 719 700 572 600 548 500 386 400 394 300 183 166 149 162 200 94 52 144 140 100 48 33 3 70 0 9 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017
XBox 360 XBox One PS 4
FIGURE 2 Xbox 360/One and Playstation 4 indie game releases
2.3 How to become independent game developer
How to become indie game developer? Is the answer something simple like get some game development tool and start doing the game? Simple answer could be Yes but to become a good (and hopefully successful) indie developer you must consider different aspects of game development. It’s not enough that you can write code there also aspects like game design, level design and marketing to consider and of course you have to have some selling idea of the game.
2.3.1 Game design
Game design is a concept of the game. It defines what the game is all about, what is done in the game, what are the rules of the game, how it’s meant to be played. If the game design is not good, it doesn’t matter how nice looking your game is. Good game design is what keeps the players playing your game. In big games, game design can also refer to
11 the theme or story of the game and in smaller “simpler” games like racing games it could refer to how the game is played.
Game design is an iterative phase, you start with an idea of the game and iteration by iteration throw some ideas to the game, keep the good ones and throw bad ones away. How can you tell, what ideas are good and what are bad? For some ideas you probably don’t know until you get some feedback from players who are actually playing your game.
Design should take into account the platform where the game is meant to be played. If the platform is a mobile device, maybe take advantage of the special functionality it offers like location detection or motion tracking?
In the indie scene, good game design is important, especially for one reason; budgets are much smaller in indie games, so you may not have time or money to create amazing graphics and sound track. On the other hand, “amazing graphics” is relative thing. What some consider beautiful, like now popular 8-bit graphics, looks horrible for some people. Indie game design should try to introduce something surprising or innovative to the player. Like in game Braid (Jonathan Blow, 2008, XBLA) which basically is just a plat- former game like Super Mario has one speciality, which is the possibility to manipulate time. This meant that player could rewind the game anytime they want to. When the player drops in to a hole and dies, she or he can just hit the rewind button to go back and try again. Time manipulation was not the first time to see in a game (e.g. Prince of Persia – Sands of time, Ubisoft, 2003 had it) but it was the essential feature of the game, so the game design was based on this game play. One example of game design where game theme plays a big role is Hotline Miami (Den- naton Games, 2012, Windows). When you first look at this game it seems like an ultra- violent top-down shooter game but its visual style and specially soundtrack is all from the 80’s, like Miami Vice. Jonathan Blow, the creator of game Braid at his speech at Game Developer Conference 2011 - Truth in Game Design, talks about methods he used when he designed the game. Game gives player ability to reverse time, so he asked questions like “What happens when you give the player unlimited ability to reverse time?” (Time index 23:50). Next step was to implement the code that answers that question. When answer to this question can be seen in the game, it can show some things that could not be for seen as an answer to this question, which raises new questions and you can ask another question like “…what if
12 we make some objects immune to the players ability to reverse time?”. Continuing this process of asking question, implement the code and asking new questions brings large volume of questions and answers. Mr. Blow brings out important point that answers were not generated by the developer they were generated by the system corresponding to the asked questions which leads to the conclusion that some way game designed itself. “Be- cause there were so many answers (generated by the system) next step was to analyse them and clean them up so that they could be best appreciated by the audience of the game.” Johnathan also talks about that game design philosophy of being open to what is here, seeing what is available and observing things. This could be explained in way that game design is not just that, you have an idea or blue print of what game should be and you dictate things that come and answer the questions yourself. Instead you should ask the questions and let the system answer the questions in other words express itself. Designer should be an observer of things and see things that are interesting.
2.3.2 Level design
Level design basically is just what it sounds like. It’s a process of designing “levels” in a game. But what is “level”? It could be stages in Mario Bros or Braid (platform games) or environments in Halo multiplayer maps or missions and goals in Call of Duty games. As can be seen “level” isn’t just a simple concept. Depending of the game, level can mean different things and it means that to make a good “level”, level designer must have a solid understanding of the game, its gameplay, story, mechanics, places, and so on.
So, what would be a good “level”?
Simplicity Jonathan Blow the creator of game Braid at his speech at Game Developer Conference 2011 - Truth in Game Design, talks about “Simplicity” design methodology he used when designing puzzle game Braid. Simplicity didn’t mean that the level is simple to resolve (and if you try the game Braid you understand that isn’t the case). He realized that when designing Braid, he wanted to make levels simpler and simpler so that they would, for example be easy to navigate and goal of the level is clear. Complications in a level were just obscuring the puzzle. Simplicity left more space for the actual puzzle.
13
Another interesting level design decision in this game Braid is that you can progress to the next level without completing all the puzzles in one level. If one level is too hard, just progress to the next and come back to the uncompleted level later. But not to make things too easy to complete the whole game, you have to solve all the puzzles in every level, before you can progress to the final level.
Rewarding There are different ways to reward player on doing something, new skill level, in-game item or completing the level could be a reward itself. Whatever the reward is, it should be something tangible so that it gives the player feeling of achievement.
Role playing games like Deus Ex: Human revolution or Fallout 3 are some examples of how to reward player with new skills. When quest is completed it gives player new skill points which can be used to improve players’ abilities.
Diablo games give player in-game items in other words “loot” like sword, shields, magic potions, etc. from concurred enemies and this loot gets better while you progress in a game, also this loot can be traded for better loot at stores.
David Braben and Ian Bell, the creators of game Elite (1984, Commodore 64, PC, Am- strad, Apple II and other computers of that time) explained their thoughts off reward in Inside Game Design (Simons, Ian). Game has a basic concept of fly around space, shoot other spaceships and avoid being shoot at. So how to make the player interested and play- ing the game? They didn’t like the idea of score, so they came up with money and how to make money? Well, you have trade, buy stuff cheap and sell for profit. When you earn money, you can improve your ship. This keeps player interested in trading which leads to money and money can be traded for improvements which is reward or achievement.
Challenge/Difficulty When comparing difficulty or challenge of the 80’s to 90’s video games to the modern video games, there is a general opinion that games back then gave player more challenge. In many cases that may be true but one thing to consider is that modern games have different design philosophy. When considering the starting point of retro games, they don’t necessary give player much instructions about how to play the game or what to do. So, they weren’t necessary very approachable games. One example would be there
14 weren’t any tutorial levels, automatic maps or hints and tips like modern games usually have, which makes them easier to approach. On the other hand, “problem” for the modern games is that they tend to hold players hand too much. They just don’t tell the player “go from place A to B and kill the bad guy” like “old” games, they say “start from place A and to get to place B, you must first go to the room D and turn the switch X which turns the elevator power on, then take to elevator to floor 2 where you find the place B”. In a way this “hand holding” has taken the joy of discovery from the players. It is said that “normal” difficulty level in modern games was “easy” in old games. One reason for this “hand holding” and easy difficulty is that big companies that make “triple A” games, makes them with big budgets. Big budgets mean that game needs to sell a lot and if the game is easy to approach and isn’t too difficult, player keeps playing it and probably will buy a sequel. Indie scene has given the game developers change to take step back to the old games when it comes to difficulty of the games.
2.3.3 Marketing
Apple App Store and Google Play each have over one million apps and roughly 20 to 30 percent of those are games. So just making a game and uploading it to store isn’t enough for the game to get attention in the game market. Emmy Jonassen at his speech Konsoll 2013: Marketing Indie Games on a $0 Budget says that “95 % of indie game are not profitable” and “80% operate at a loss”. So, there is great change that, without any marketing indie game developer will go in to those per- centages and the game will disappear in the oblivion of app store. This means that game developers can’t neglect the marketing aspect. But what are the possibilities for indie game developer to promote the game, if budget for marketing is small or even zero?
Start marketing early Most of the games sales are made in the first weeks or even days after it has been released so game must have some kind of “hype” before that. To make the hype public has to have knowledge of the games existence. Good point to start marketing is when the game has something good enough to show to the public. This could be some screenshots of the game, story line, or playable demo. Whatever it is, it should be given some thought before
15 publishing it. One example would be art work, which is still in the development phase (done by the programmer and not by graphics designer), are they worth publishing? Are they good enough to get public interested? Probably not…
How to start marketing the game? One place to start marketing the game is social media. Facebook, Twitter, Google+, In- stagram, YouTube, etc. all good places to start the campaign. Whatever the place it needs some active involvement like a blog and steady updates to keep the public interested. Updates to the blog should not all just be some technical/clinical stuff about the game. It needs to tell something personal about the developer themselves (like personal struggles) so that the readers get to know the person behind the game. Indie Game – The Movie is a good example (although it’s a little bit more than just a blog) where the audience learns about the creators of the game Braid, Fez and Super Meat Boy. Another thing about the updates is that it needs to have some major points like trailers or playable demos. Another place would be a concentrated web page but that needs some social media mar- keting before that so that the public learns about the existence of the page.
16
3 Game Development Tools
Now days it is relatively easy to start creating games (creating good games is another thing…). Instead of building game from scratch or creating game engine, there are many free game development tools that offer tools for creating 2d or 3d games. Many of them support cross-platform development so you can easily export same game to different plat- forms.
3.1 Microsoft XNA Game Studio/MonoGame
Microsoft XNA Game Studio is a programming environment for Microsoft Visual Studio. It provides framework and tools to create games for Xbox360 consoles, Windows Phone and Windows PCs. Current version of XNA Game Studio is 4.0 and since Microsoft has announced that it’s not going to release future versions of it but MonoGame which is an open source implementation of XNA will continue to support it. Popular indie games created with XNA Game Studio includes titles like; platformer Fez (Polytron Corpora- tion, 2012), action role playing game Bastion (Supergiant Games, 2011) and Dead Pixels (CSR-Studios, 2012).
3.2 GameMaker: Studio
GameMaker: Studio (YoYo Games) is a game development environment targeted for novice programmers who don’t have much experience on programming. It provides drag and drop system to build action sequences, sandboxed scripting language and cross-plat- form development. One of the best known indie game created with GameMaker is Hotline Miami (Dennaton Games, 2012).
3.3 Adventure Game Studio
Adventure Game Studio (Chris Jones, 1997) is game development environment mainly to build graphical adventure games like classic LucasArts games Maniac Mansion and Monkey Island. Actually, some of the old adventure games has been remade with AGS like Maniac Mansion, Kings Quest and Space Quest.
17
4 Unity – Game Engine
Unity is multiplatform game development engine, currently it supports over 17 different platforms like Windows, Xbox (360 and One), iOS, Android and Windows Phone. It gives tools for creating 2D and 3D type of games. Examples of popular games made with Unity are Cities Skylines (Colossal Order, 2015), Ori and the Blind Forest (Moon Studios, 2015) and Broforce (Free Lives, 2015)
4.1.1 Learning the Unity
Good place to start learning Unity3D is to go to their web site unity3d.com. There are lot of tutorials, examples, videos and live sessions to get you started.
FIGURE 3. Unity tutorials
18
FIGURE 4 Unity 2D lessons
FIGURE 5 Unity Community
19
FIGURE 6 Unity in YouTube
4.1.2 Unity Asset store
Unity Asset Store is place where you can find readymade components like 3D models, textures, scripts and animation tools for your game. Some of them are free and some not. Anyone using Unity can submit their creations to Asset Store and set their price or set them as no charge. Each sale gives submitter 70% cut of the sale. These assets or addons can ease the pain of creating all by yourself.
20
FIGURE 7 Unity Asset Store
21
5 Tapper game
Tapper (or Root Beer Tapper) is an arcade game originally released in 1983. Different versions of the game have been released for platforms like Nintendo Entertainment Sys- tem (NES), Commodore 64 and modern consoles like Xbox360. Goal in the game is to serve beer, collect empty mugs and tips. Customers are moving towards the bartender and when player serves them a beer they move out. If player fails to serve beer on time and customer reaches the end of the bar table, it grabs the player and toss him out of the bar which results as loss of life. When enough lives are lost game ends.
FIGURE 8 Tapper game
(http://en.wikipedia.org/wiki/Tapper)
22
6 2D Game Development with Unity
Unity offers the tools to create basically any kind of game, but this hands-on part of this thesis will focus on the idea of the Tapper game. Goal is to learn some basic concepts of Unity tool like the meaning of scene, scaling, canvas, prefabs, interacting with the game, collision detection and enemy spawning.
6.1 Creating the 2D project
Unity has a support for 2D and 3D projects. Unity project can be marked as 2D project which sets default settings in editor and views to 2D mode.
FIGURE 9 Unity Project Wizard - 2D mode selected
When scene view is set in 2D mode movement is limited to X and Y axis when in 3D mode movement would also be possible in Z axis.
23
FIGURE 10 Scene view in 2D mode
FIGURE 11 Scene view in 3D mode
24
Editor settings have default behaviour mode selection which can be set as 3D or 2D. When new 2D project is created then editor settings already have 2D mode selected. Ed- itor’s behaviour mode can be changed to 3D even when creating 2D project. Behaviour mode 2D means that when new scene is created, default camera is created with projection Orthographic and size 5. Also, it means that when new image is imported it has texture type Sprite instead of Texture.
FIGURE 12 Editor settings
6.1.1 Creating the scene
Game creation starts by creating the first level which in this case will be a bar. Action in the scene happens in one screen so we can create the scene by creating and importing one sprite image to the Unity editor. Importing image to Unity is very simple, just drag and drop the image to editor. Hard part is to draw the actual image. To get started with the game development we can create the first version of the scene image by taking some Tapper game image from the Internet and modifying it a bit with Paint or Photoshop so that it fits our needs and use that for now.
25
FIGURE 13 Scene 1 background image imported FIGURE 13 shows imported image and its information in the Inspector view. In the Game view, aspect ratio has been set to 16:9 which is the common ratio for mobile phones. Basic folder structure has been created under Assets and it contains folders _Scenes, Sprites and Scripts.
6.1.2 Scene background
Putting the background to the scene is done by dragging the image to the scene view. After it’s done, image is shown also in the hierarchy view. When image is selected in the hierarchy view its information like position is shown in the Inspector view.
Game is designed to be played on mobile phones with landscape orientation and to make game support different screen sizes we need to make the image scale automatically ac- cording to devices screen size. Limiting the orientation of the game to landscape can be done from the build settings.
There are different ways to create script in Unity, one way is to add script component to the image from the Inspector view. One thing to notice is that by default script files are
26 created at the root level of Assets folder but we can drag and drop it to our Scripts folder. Once the script file has been created it can be opened in MonoDevelop or Visual Studio editor.
FIGURE 14 Background with Script component “ImageRescaler”
6.1.3 Automatic scaling
Game is meant to be run on mobile devices so there is no fixed screen size, so we must do some automatic scaling for images. This scrip is added to the background so that it effects all other images inside it like our bartender which is added later.
27
using UnityEngine; using System.Collections;
public class ImageRescaler : MonoBehaviour {
void Awake() { print ("--ImageRescaler.Awake"); //Get reference to the sprite renderer which displays images on Unity SpriteRenderer sr = GetComponent
//Scale the object where this script is attached to its original size. transform.localScale = new Vector3(1,1,1);
//Calculate width and height of the image float width = sr.sprite.bounds.size.x; float height = sr.sprite.bounds.size.y;
//Calculate height and with of the screen float worldScreenHeight = Camera.main.orthographicSize*2f; float worldScreenWidth = worldScreenHeight/Screen.height*Screen.width;
//Scale image width Vector3 xWidth = transform.localScale; xWidth.x = worldScreenWidth / width; transform.localScale = xWidth;
//Scale image height Vector3 yHeight = transform.localScale; yHeight.y = worldScreenHeight / height; transform.localScale = yHeight; } } Figure 15 ImageRescaler
6.2 Player object
Our hero of the game is a bartender. Bartender is a simple game object that consists of Sprite Renderer. Bartender is created from the Game Object menu and selecting Create Empty. To our new game object, we just specify some name and select the bartender sprite in the Sprite Renderer. It doesn’t matter where this game object is added on the screen because it will be moved programmatically around movement points.
28
Figure 16 Our lonely hero
6.2.1 Player movement points
Player will be moving between four static points. Each point is located at the end of bar counter. These points are specified by creating empty game objects from the Game Object menu and selecting Create Empty. Once game object is created it is first located and shown in the Scene view at the position of X = 0, Y = 0 and Z = 0. From there they need to be moved to their correct location. Important thing to notice is that, because the back- ground is scaling automatically these points need to be moved in the Hierarchy view under the background image so that these points stay at their correct locations when the background image scales. FIGURE 17 Player movement pointsshows player movement points presented with stars (these stars are just presenting purposes, they will be re- moved).
29
FIGURE 17 Player movement points
6.2.2 Canvas
Once the movement points have been defined we need to make the player move between these points. For that we first need buttons which will move player up and down.
For UI components we will use Canvas which is a new feature introduced in the Unity version 4.6. Canvas is a root component for all UI elements like buttons and scene can have multiple canvases. Canvas has three different render modes which define how UI elements are drawn on the scene. Render modes are Screen Space – Overlay, Screen Space – Camera and World Space. In the Overlay mode canvas will overlay the scene and all UI elements will be drawn on top the screen also the canvas fills the scene auto- matically. Canvas will resize automatically if the screen size changes, so we don’t have to worry about the scaling like we had to when creating the scene background image. Render mode Camera is similar to overlay mode except that in this mode Canvas is ren- dered by a specific camera in the scene and this allows camera specific settings to be applied in the canvas.
When button is created it will also create canvas if it hasn’t been created already. Button has a two required elements Image script and Button script and optional Label element which can be removed if the button doesn’t need any text. Buttons image element can have some specified image which is shown as button. Button script defines what happens
30 when the button is clicked. One thing to notice is that in the Scene View Canvas is shown quite large but in the Game view and when the game is run canvas is resized and the buttons can be seen at their correct places.
FIGURE 18 Movement buttons in the Scene view
FIGURE 19 Game running. Buttons showing at their defined locations
31
6.2.3 Moving the player character
Now that the canvas and the movement buttons have been created it is time to make the player move.
In the first step, player image is first imported to the Assets view and from there it is drag and dropped to the scene. In the hierarchy view, it is located at the root level. Next step is to attach script to the buttons that handles the player movement.
For the movement script we create empty game object, rename it to MovementController and attach script to it.
Public variables and initialization
First in the script we define two un-initialized public variables. Declaring these variables public makes it possible to set their initial values in the editor view.
// The player game object (e.g. image) reference. public GameObject playerImage;
// The player position objects array. public GameObject[] playerPositions;
FIGURE 20 playerImage and playerPositions variables in the editor view, un-initialized.
32
First variable playerImage is GameObject type that will be initialized with our player image. Initial value for it is given by drag and dropping game object tapper_player from the Hierarchy view over the empty box in the Player Image section in the Inspector view. Other variable playerPostions is an array of GameObjects that will hold our player move- ment positions game objects. Initial values for it is given by drag and dropping game objects PlayerPoint1, PlayerPoint2, PlayerPoint3 and PlayerPoint4 from the Hierarchy view over the Player Positions text.
FIGURE 21 Initialized playerImage and playerPositions variables
Public methods and button onClick() action
Next thing to do is to define some variables and public methods that will be use in the actual movement:
// Movement direction up or down. private enum EMovementDirection { UP, DOWN };
33
// Static variable that keeps track of the current position in playerPositions array. private static int positionInArray = 0;
// Moves player one step up in the positions. public void MovePlayerUp() { MovePlayer(EMovementDirection.UP); }
// Moves player one step down in the positions. public void MovePlayerDown() { MovePlayer(EMovementDirection.DOWN); }
MovePlayerUp() and MovePlayerDown() are just simple methods that define the move- ment direction and call private method MovePlayer() that will handle the actual move- ment.
Public methods can be set to execute on button click. This is done in the Inspector view. Button has a On Click() Event component where can be selected which script and method to call when button is clicked. Button Up is set to call MovementController.MovePlay- erUp() method and Button Up is set to call MoveMentController.MovePlayerDown() method.
FIGURE 22 “Button Up” - Button On Click() component.
34
FIGURE 23 “Button Up” - Just after ‘+’ has been clicked. No script or method selected.
FIGURE 24 “Button Up” - MovementController script selected and list of methods.
35
FIGURE 25 “Button Up” - MovementController.MovePlayerUp method selected.
36
using UnityEngine; using System.Collections;
public class MovementController : MonoBehaviour {
// The player game object (e.g. image) reference. public GameObject playerImage;
// The player position objects array. public GameObject[] playerPositions;
// Movement direction up or down. private enum EMovementDirection { UP, DOWN };
// Static variable that keeps track of the current position in playerPositions array. private static int positionInArray = 0;
// On Start move player to the first position. public void Start() { print("--MovementController.Start: " + playerPositions.Length); MovePlayerToFirstPosition(); }
// Sets current position to the first position and moves player object there. public void MovePlayerToFirstPosition() { print("--MovePlayerToFirstPosition"); positionInArray = 0; MovePlayerToPosition(); }
// Moves player one step up in the positions. public void MovePlayerUp() { MovePlayer(EMovementDirection.UP); }
// Moves player one step down in the positions. public void MovePlayerDown() { MovePlayer(EMovementDirection.DOWN); }
// Moves player up or down depending on given parameter. private void MovePlayer(EMovementDirection movementDirection) { print("--MovePlayer: " + movementDirection); if (movementDirection == EMovementDirection.UP) { positionInArray++; } else if (movementDirection == EMovementDirection.DOWN) { if (positionInArray <= 0) { positionInArray = playerPositions.Length; } positionInArray--; }
if (positionInArray >= playerPositions.Length) { positionInArray = 0; } MovePlayerToPosition(); }
// Moves player to the current position private void MovePlayerToPosition() { print("--MovePlayerToPosition: " + positionInArray); playerImage.transform.position = playerPositions[positionInArray].transform.position; } } FIGURE 26 Full source code for MovementController
37
6.3 Enemy (aka customer) objects
6.3.1 Enemy objects
Game contains multiple “enemies”, so creating them all individually would be a pretty big job. Instead we create prefabs which are kind a like templates for the re-usable game objects. Prefabs are like normal game objects, they have components and settings. Instances of the prefab are basically copies of it, but they can override components and settings of the original and these overrides don’t affect each other. Changes that are made in the original prefab is reflected to all instances. Prefabs are simple to create. Like any other game object, we first create empty game object in the scene or in the hierarchy view. To our empty game object, we give it just a Sprite Render and assign picture to it. After this when we drag and drop it to Project views Prefabs folder and that creates our first prefab in the Prefabs folder.
FIGURE 27 - Enemy1 drag and drop to Prefabs folder After game object exists in the Prefabs folder it can be deleted from the scene or from the Hierarchy view.
38
6.3.2 Spawning the enemies
After enemy prefab has been created next step is to start spawning them. First step is to define enemy spawn points. Spawn points are created in a similar way as the player move- ment points were created, by adding empty game object in places were the enemies are spawning.
FIGURE 28 - Enemy spawn points
After the spawn points are created next step is to write a script that handles the actual spawning. EnemySpawner shown in FIGURE 30 is a script that spawns enemies in a ran- dom spawn points. After the game starts, EnemySpawner script starts spawning enemies in waves. It is possible to configure how many waves are spawned and how many enemies are in each wave, also it is possible to define time between each wave. For the clarity, script is attached to the empty game object and our enemy1 prefab is drag and dropped to the Enemies array shown in Inspector. Enemy spawn points are drag and dropped to Spawn Locations folder (FIGURE 29).
39
FIGURE 29 - Enemy spawner
40
using UnityEngine; using System.Collections;
public class EnemySpawner : MonoBehaviour {
// Locations where to spawn enemies public Transform[] spawnLocations;
// Enemy game objects public GameObject[] enemies;
// Time between each spawn public float timeBetweenWaves = 1.0f;
// Number of waves to spawn before stop spawning public float numberOfWaves = 5.0f;
// Number of spwaned enemies at each wave public float numberOfSpawnedEnemies = 3.0f;
// Delay before start spawning when game starts private static float SPAWN_DELAY = 2.0f;
// Delay between enemies. If two sequential enemies are spawned // at the same location this makes sure that they dont get spawned on top of each other. private static float DELAY_BETWEEN_ENEMIES = 0.25f;
// Use this for initialization void Start () { // Start couroutine StartCoroutine (doSpawning ()); }
private IEnumerator doSpawning () { // Wait a bit before starting spawning yield return new WaitForSeconds (SPAWN_DELAY);
Debug.Log ("--doSpawning");
// Current wave counter int currentWave = 0;
// Start infitive loop which will be stopped after all waves are completed while (currentWave < numberOfWaves) { Debug.Log ("--Start wave " + currentWave + ", " + Time.time); for (int i = 0; i < numberOfSpawnedEnemies; i++) { spawnEnemy (); yield return new WaitForSeconds (DELAY_BETWEEN_ENEMIES); }
currentWave++;
// Wait between waves yield return new WaitForSeconds (timeBetweenWaves); } }
// Spawn single random enemy at single random point private void spawnEnemy () { // Select random spawn point index int spawnPointIndex = Random.Range (0, spawnLocations.Length);
// Select random enemy GameObject enemy = enemies [Random.Range (0, enemies.Length)];
// Create instance of the enemy Instantiate (enemy, spawnLocations [spawnPointIndex].position, Quaternion.identity); } }
FIGURE 30 Full source code for EnemySpawner
41
Because we need to pause the code execution between waves and every enemy, spawning is done in a coroutine private IEnumerator doSpawning (). Coroutines are like functions but they have the ability to pause the code execution with yield. With yield it is possible to pause the execution for specified seconds (WaitForSeconds).
At this point when game is started our spawning script just creates enemies in these static points (FIGURE 31) and they are not moving so next step is to make the enemies to move.
FIGURE 31 EnemySpawner at work. Enemies have been spawned at four points, but they are not moving.
6.3.3 Moving the enemies
To make the enemy to move it needs two more components, rigid body and scrip. From the Inspector view using Add component we add Rigidbody 2D and new script named EnemyPhysics.
For the Rigidbody 2D it is important to set gravity scale as zero. That defines that the gravity is not affecting the object. If gravity scale is set to something other than, it would mean that the object would start falling when it is spawned (FIGURE 32).
Enemy physics script presents two public variables minSpeed and maxSpeed. Those var- iables are public so that it is easy to adjust movement speed from the Inspector view. Script is quite simple, it adds force to the rigid body of the enemy1 object and that makes it move (FIGURE 33).
42
After the rigid body 2D and script are at place we can try to run the game. Now the ene- mies are moving (FIGURE 34) but the movement never stops, so next step is to add some collision detection to it.
FIGURE 32 enemy1's gravity scale set as zero (0)
using UnityEngine; using System.Collections;
public class EnemyPhysics : MonoBehaviour {
// Minimum speed of the object. public float minSpeed = 1.0f;
// Maximum speed of the object. public float maxSpeed = 3.0f;
void Start () { // This is just to verify that min speed is never below 0.5 // Negative speed would make the object move backwards. if (minSpeed < 0.5f) { minSpeed = 0.5f; }
// Get rigid body object Rigidbody2D rb = GetComponent
// Set random speed between min and max speed float forceX = Random.Range (minSpeed, maxSpeed);
// Create force vector to present movement to right. // First parameter presents x vector and second parameter y vector. // Positive first parameter presents movement to right. Negative would be left. // Second parameter as 0 defines that it’s not moving up or down. Vector2 forceVectorRight = new Vector2 (forceX, 0);
// Add force to rigidbody. This makes the object to move. rb.AddForce(forceVectorRight, ForceMode2D.Impulse); } } FIGURE 33 Full source code for EnemyPhysics
43
FIGURE 34 Enemies are moving but the movement never stops
6.4 Collision system
Box collider First, we need to add Box Collider 2D component to our enemy1 prefab from the Inspector view (Select enemy1 from prefabs -> Add component -> Physics 2D -> Box Collider 2D). Box Collider 2D like the name suggests is a rectangle in a specific position with height and width. In our case position is the position where our enemy is. When added to the enemy1 the width and height of the box is automatically the size of our enemy1 sprite, but the size is not tided to that. Size of the box can be edited bigger or smaller.
44
FIGURE 35 Enemy with Box Collider 2D Now that the enemies have box colliders they would be colliding with each other also. This is not wanted so we need to add enemies to a specific layer and adjust project physics settings so that objects in this layer are not colliding with each other.
Layers Layers can be created from the from the Inspector view while enemy1 prefab is selected using Add Layer (FIGURE 36).
FIGURE 36 enemy1 prefab with specific layer
Collision matrix
45
Now that the enemies are in the Enemy layer we need to adjust project physics settings (Edit -> Project Settings -> Physics 2D) (FIGURE 37).
FIGURE 37 Project physics settings
From the collision matrix unselecting Enemy – Enemy checkbox sets the enemies not to collide with each other (FIGURE 38).
46
FIGURE 38 Project collision matrix
Reaching the end of the bar tables Enemies are now moving, and they have box colliders that react when they collide with other colliders. Next step is to add colliders at the end of the bar tables so that we can stop movement of the enemies. Starting with empty game object (GameObject -> Create Empty) four Edge Collider 2D components are added to it. Edge Colliders consists of line segments and it can be simple as straight line or more complex form like L-shape. Points of those four edge colliders are modified so that they locate at the end of the bar tables (FIGURE 39).
47
FIGURE 39 Edge colliders at the end of the bar tables
FIGURE 40 Game running. Enemies stop at the end of the bar tables because they hit the edge colliders For later purposes one more adjustment is needed for the colliders. In the Inspector view, using “Add tag” and “Add layer” they are tagged as “EnemyFrontCollider” and also added to the similarly named layer (FIGURE 41).
48
FIGURE 41 Enemy colliders marked with tag and added to the special layer
When enemy hits the collider, it could star some event like decreasing points or kill the player. In the original Tapper game when the customer reaches the end of the bar table it grasps the bartender, drag him through the table and player loses a life and when enough lives are lost its Game Over.
6.5 Serving the drinks
Now that we have some enemies moving and player has the ability to move the bartender next thing is to give the player ability to serve some drinks. To make this happen we can use the same methods that have been used earlier. First new brefab “Glass” is created with components Rigidbody2D, BoxCollider2D and two scripts. One script contains physics to make the glass move when instantiated and other for collision detection. For Rigidbody2D Gravity Scale is set to 0 to prevent glass falling from the screen. Also new layer “Glass” is defined.
49
Figure 42 Glass prefab Scripts for the glass prefab are pretty simple. First scrip makes the glass move when glass instance is created. What makes this script different from the EnemyPhysics which moves the enemy is the use of FixedUpdate() method and setting the glass objects velocity di- rectly. Unity documentation says that this method is not usually used which makes the EnemyPhysics way of moving better but for learning purposes we try this method. (https://docs.unity3d.com/ScriptReference/Rigidbody2D-velocity.html)
50
using UnityEngine; using System.Collections;
public class GlassPhysics : MonoBehaviour { private Vector2 speedLeft = new Vector2 (-3, 0);
//This function is called every fixed framerate frame, if the MonoBehaviour is enabled. void FixedUpdate () { // Set objects velocity every framerate. Note! this value is not usually set directly // but rather by using forces like in the enemy physics but for learning purposes lets use this for now. GetComponent
Another scrip defines that if collision is made with enemy object it is destroyed. Also, the glass object itself is destroyed. Detection of enemy is just simple if -statement with check- ing of objects tag.
using UnityEngine; using System.Collections;
public class GlassCollision : MonoBehaviour {
void OnCollisionEnter2D(Collision2D coll) { print ("--Collision: " + coll.gameObject.tag);
//If hits enemy if (coll.gameObject.tag == "Enemy") { //Destroy self Destroy(gameObject);
//Destroy collided enemy Destroy(coll.gameObject); } }
Last step is to extend MovementController script with new public method ServeDrink (Figure 44) which instantiates glass object to the players position and to add new button “SERVE” (Figure 45) with “On Click()” event to call that method.
51
… // Glass prefab object that is served public Transform glass;
public class MovementController : MonoBehaviour { …
//Instantiate glass prefab object to the place where player is positioned public void ServeDrink () { Instantiate(glass, playerImage.transform.position, Quaternion.iden- tity); } … }
Figure 44 MovementController extended with ServeDrink() method
Figure 45 Serve button with OnClick event
52
Oh, and one more thing is needed. Collision matrix needs some adjustment. We don’t want our glass to make collision with the bar table end points. If it would collide it would stop the glass from moving (Figure 46).
Figure 46 Prevent glass from colliding with the bar table end points
Now all things should be in place and player has the ability to serve some drinks.
53
Figure 47 Some beers are served
6.6 Ending the game
When the enemy reaches the end of the bar table it means that player has failed and should result as a lost life and when enough lives are lost its game over. For now, we just stop enemy spawning and show Restart -button that can be used to restart the game.
6.6.1 Restart game button
First, we extend MovementController with simple public method that reloads Scene1 (Figure 48).
54
… using UnityEngine.SceneManagement;
public class MovementController : MonoBehaviour { …
public void RestartGame() { //Load Scene 1 SceneManager.LoadScene("Scene1"); } … }
Figure 48 MovementController extended with public method RestartGame()
Next we add UI button similar to Button Up/Down and set its OnClick() method to call MovementController.RestartGame(). Also, we give it a new script component and name it Restart (Figure 49).
Figure 49 New Restart UI button Restart script is simple script that hides the button on Start and offers public method to unhide it (Figure 50).
55
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;
public class Restart : MonoBehaviour {
Button restartButton;
void Start () { restartButton = GetComponent
public void ShowRestartButton() { Debug.Log("--Show restart button"); restartButton.gameObject.SetActive(true); } } Figure 50 Simple Restart Button script
6.6.2 Collision event to stop enemy spawning and to show Restart button
For the bar table end points new component Script is added and its named EndGame.
Figure 51 Bar table end points with Script component
Now that we have Edge Collider 2Ds added to our Bar table end points they trigger
56
OnCollisionEnter2D() event when enemies hit them. We can use this event in our End- Game Script to do things that we need to end the game. To stop enemy spawning we modify our EnemySpawner script with boolean that tells if our game is running or not and with public method StopSpawning() that can be called from our EndGame script.
public class EnemySpawner : MonoBehaviour {
… // Defines if the game is running or not private bool isGameRunning = true; …
// Public method that can be called from other scripts to stop spawning public void StopSpawning() { Debug.Log("--End game"); isGameRunning = false; }
private IEnumerator doSpawning () { …
// Start infitive loop which will be stopped after all waves are // AND our game is running while (isGameRunning && (currentWave < numberOfWaves)) { … }
… } Figure 52 – Additions to the EnemySpawner script. New public method and isGameRunning boolean
EndGame script is modified so that it calls EnemySpawner.StopSpawning() when colli- sion event occurs.
57
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class EndGame : MonoBehaviour {
public EnemySpawner spawnerScript; public Restart restartScript;
void Awake() { Debug.Log("End Game Awake"); // Scripts are set to game objects so we need to get reference // to those first using "find" before getting reference // to the actual scripts. spawnerScript = GameObject.Find("Enemy spawner") .GetComponent
// This event is triggered when collision happens void OnCollisionEnter2D(Collision2D coll) { //If hits enemy if (coll.gameObject.tag == "Enemy") { Debug.Log("--Collision with enemy"); stopSpawning(); showRestartButton(); } }
private void stopSpawning() { spawnerScript.StopSpawning(); }
private void showRestartButton() { restartScript.ShowRestartButton(); } }
Figure 53 - EndGame script
EndGame script is pretty simple there is method OnCollisionEnter2D which is automat- ically called when some object make collision with our Edge Collider 2D. Inside the method there is if statement that checks the game objects tag and if its “Enemy” it calls stopSpawning() and showRestartButton(). One more thing needs to be done, “Enemy” tag is not yet existing so new tag is added for the enemy prefab and its name “Enemy”.
58
Figure 54 Tagged enemy
Now that the “Enemy” tag is added we can run the game and test it. When the enemy reaches the end of the table enemies stop spawning and restart button is shown (Figure 55).
Figure 55 Game Over
59
And when the Restart -button is pressed game reloads scene1 and starts over.
60
7 Final words
This thesis has been long in the making process. When I started this process back in year 2014, Windows Phone was still alive and Unity tool supported that platform. During 2017 Microsoft cancelled the platform and newer versions of Unity stopped supporting it.
Original title of this thesis was “Independent game development for Windows Phone” or something like that and some of my goals was to learn what it means to be independent game developer and how to make games for Windows Phone, so that someday I could implement my own idea of the game and make a million bucks. Well, did I achieve those goals?
I’m not a millionaire (yet) so that plan bombed (well maybe that plan wasn’t so realistic to begin with). About the game making process I would say I got a glimpse look of it. It was interesting to read about game development and watch videos about the “real” indie game makers, like Phil Fish, Jonathan Blow, Edmund McCillen and Tommy Refenes in the movie “Indie Game: The Movie”. Creating games is not just that you have an idea. If you are a lonely developer or small group of indie developers, most of all you have to have passion to drive that idea in to actual game.
About my passion for video games, I always liked playing them and wanted to create some and during this thesis making I learned that it is easy to start creating something with the modern game creation engines like Unity. Creating something good and selling is another thing.
During this process I got idea for the game which sounds really good and started to im- plement that idea to actual game (I will keep that idea as a secret for now). For about four to six months I had that passion to make it happen. After work days and weekends, I tried to spend as much time as I could on a computer, developing. First my idea was a 3d game but after couple of weeks I realized that was too ambitious for a first game, so I changed it to 2d. More time went by and it started to look that after work and weekends weren’t enough time and slowly the passion started to fade and one day it was gone. Maybe it was the fact that I’m a coder and I have no graphical skills to make good looking game or composer skill to make good soundtrack or perhaps that I have a family (2 kids and a wife) and a job that takes also time. Perhaps all those together… Maybe someday that
61 passion will rise again but for now I will just settle for playing the games. And next time I think that something simpler game is better way to start and plan a head little bit better.
One another goal was to learn how to make games for Windows Phone. About that I learned that it doesn’t matter so much what is your planned platform. Game engine tools like Unity support multiple platforms (no longer Windows Phone though) so game devel- opment is not tied to some platforms language. You can code with engines supported language like C# and export it different platforms. But giving some thought about decid- ing if it’s a mobile or PC platform gives you possibilities to use platform specific features like mobile devices location service and mobile devices have smaller screen than PC monitors. Today’s mobile platforms are quite powerful so unless you are creating exten- sive game there is no need to restrict it to PC only. During this project I tested the Tapper on my Lumia phone, but that option is no longer available because Windows Phones are no longer supported by Unity.
One key thing about game making was left out in this thesis and that is the actual pub- lishing of the game. Tapper game wasn’t meant to be published anyway and my own idea of the game newer saw the day light, but perhaps someday it will…
-Niko
62
REFERENCIES
Pierce, Gregory, 2011. Unity iOS Game Development. Course Technology.
Alessi, Jeremy, 2012. iPhone 3D Game Programming All in One. Packt Publishing Ltd.
Thompshon, Jim, 2007. Game design course: principles, practice, and techniques - the ultimate guide for the aspiring game designer
Simons, Ian, 2007. Inside Game Design
Blow, Jonathan, 2011, speech at Game Developer Conference - Truth in Game Design (https://www.youtube.com/watch?v=XwhEl6mGgLg, http://gdcvault.com/play/1014982/Truth-in-Game
Marketing related: Jonassen, Emmy, 2013, speech at Konsoll: Marketing Indie Games on a $0 Budg et http://www.indiegamegirl.com/no-budget-marketing/ https://www.youtube.com/watch?t=183&v=SkEQtMP2CuA
Sinclair, Brendan, 2013, article: Indies: Market early and often or "sink into obscurity" http://www.gamesindustry.biz/articles/2013-10-30-indies-market-early-and-often-or- sink-into-obscurity
DellaFave, Robert, 2014, article: Marketing Your Indie Game: The Single Most Im- portant Thing That No One Knows How to Do http://gamedevelopment.tutsplus.com/articles/marketing-your-indie-game-the-single- most-important-thing-that-no-one-knows-how-to-do--gamedev-7157
Indie Game Development the Movie, 2012, Lisanne Pajot, James Swirsky