Explore Free Unity Multiplayer Game Tutorials – GameDev Academy https://gamedevacademy.org Tutorials on Game Development, Unity, Phaser and HTML5 Thu, 23 Feb 2023 21:14:35 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://gamedevacademy.org/wp-content/uploads/2015/09/cropped-GDA_logofinal_2015-h70-32x32.png Explore Free Unity Multiplayer Game Tutorials – GameDev Academy https://gamedevacademy.org 32 32 How to Create a Multiplayer Game in Unity https://gamedevacademy.org/how-to-create-a-multiplayer-game-in-unity/ Mon, 19 Dec 2022 09:13:56 +0000 https://gamedevacademy.org/?p=4819 Read more]]> In this tutorial, we are going to build a simple demo to learn how to use Unity multiplayer features. Our game will have a single scene where we will implement a multiplayer Space Shooter. In our demo multiple players will be able to join the same game to shoot enemies that will be randomly spawned.

In order to follow this tutorial, you are expected to be familiar with the following concepts:

  • C# programming
  • Using Unity Editor, such as importing assets, creating prefabs and adding components

We’ll be using an asset known as Mirror. This is an expansion on Unity’s default networking system, adding in new features and fixing a large amount of bugs and problems.

Before You Begin

This tutorial assumes basic familiarity with Unity. If this is your first time into the world of Unity, we first suggest learning through some of our free Unity tutorials or through some amazing online courses.

For teachers wanting to incorporate Unity into the classroom or into school-related activities, Zenva Schools is also an option. This platform offers Unity courses for classroom use alongside useful features such as course plans, classroom management tools, reporting, and more.

Creating Project and Importing Assets

Before starting to read the tutorial, you need to create a new Unity project and import all sprites available through the source code. In order to do that, create a folder called Sprites and copy all sprites to this folder. Unity Inspector will automatically import them to your project.

However, some of those sprites are in spritesheets, such as the enemies spritesheets, and they need to be sliced. In order to do that, we need to set the Sprite Mode as Multiple and open the Sprite Editor.

Importing sprite assets.

In the Sprite Editor (shown below), you need to open the slice menu and click in the Slice button, with the slice type as automatic. Finally, hit apply before closing.

Unity sprite editor.

We also need to import the Mirror asset. Go to the Asset Store (Window > Asset Store) and download “Mirror”.

Downloading Mirror from the Asset Store.

Source Code Files

You can download the tutorial source code files here.

BUILD YOUR OWN GAMES

Get 250+ coding courses for

$1

AVAILABLE FOR A LIMITED TIME ONLY

Background canvas

The first thing we are going to do is creating a background canvas to show a background image.

We can do that by creating a new Image in the Hierarchy, and it will automatically create a new Canvas (rename it to BackgroundCanvas).

In the BackgroundCanvas, we need to set its Render Mode to be Screen Space – Camera (remember to attach your Main Camera to it). Then, we are going to set its UI Scale Mode to Scale With Screen Size. This way the Canvas will appear in the background, and not in front of the other objects.

Creating the background canvas game object.

In the BackgroundImage we only need to set the Source Image, which will be the space one.

Creating the background image with Unity's UI.

Try running the game now and you should see the space background in the game.

Background star image.

Network Manager

In order to have a multiplayer game, we need a GameObject with the NetworkManager and NetworkManagerHUD components, so let’s create one.

Network manager using Unity's networking framework and Mirror.

This object will be responsible for managing for connecting different clients in a game and synchronizing the game objects among all clients. The Network Manager HUD shows a simple HUD for the players to connect to a game.

For example, if you play the game now, you should see the following screen:

What the game looks like right now.

In this tutorial we are going to use the LAN Host and LAN Client options. Unity multiplayer games work in the following way: first, a player starts a game as host (by selecting LAN Host). A host works as a client and a server at the same time. Then, other players can connect to this host by as clients (by selecting LAN Client). The client communicates with the server, but do not execute any server only code. So, in order to test our game we are going to open two instances of it, one as the Host and another as the Client.

However, you can not open two instances of the game in the Unity Editor. In order to do so, you need to build your game and run the first instance from the generated executable file. The second instance can be run from the Unity Editor (in the Play Mode).

In order to build your game you need to add the Game scene to the build. So, go to File -> Build Settings and add the Game scene to build. Then, you can generate and executable file and run it by clicking on File -> Build & Run. This will open a new window with the game. After doing that, you can enter Play Mode in the Unity Editor to run the second instance of the game. This is what we are going to do every time we need to test a multiplayer game.

Unity build settings.

Ship Movement

Now that we have the NetworkManager, we can start creating the game objects which will be managed by it. The first one we are going to create is the player ship.

For now, the ship will only move horizontally in the screen, with its position being updated by the NetworkManager. Later on, we are going to add to it the ability to shoot bullets and receive damage.

So, first of all, create a new GameObject called Ship and make it a prefab. The figure below shows the Ship prefab components, which I will explain now.

Player ship object with Unity mirror networking components.

In order to a game object to be managed by the NetworkManager, we need to add the NetworkIdentity component to it. In addition, since the ship will be controlled by the player, we are going to set the Local Player Authority check box for it.

The NetworkTransform component, by its turn, is responsible for updating the Ship position throughout the server and all the clients. Otherwise, if we’ve moved the ship in one screen, its position wouldn’t be updated in the other screens. NetworkIdentity and NetworkTransform are the two components necessary for multiplayer features. Enable Client Authority on the NetworkTransform component.

Now, to handle movement and collisions, we need to add a RigidBody2D and a BoxCollider2D. In addition, the BoxCollider2D will be a trigger (Is Trigger set to true), since we don’t want collisions to affect the ship physics.

Finally, we are going to add a MoveShip script, which will have a Speed parameter. Other scripts will be added later, but that’s it for now.

The MoveShip script is very simple, in the FixedUpdate method we get the movement from the Horizontal Axis and set the ship velocity accordingly. However, there are two very important network-related things that must be explained.

First, typically all Scripts in a Unity game inherits MonoBehaviour to use its API. However, in order to use the Network API the script must inherit NetworkBehaviour instead of MonoBehaviour. You need to inlcude the Networking namespace (using UnityEngine.Networking) in order to do that.

Also, in a Unity multiplayer game, the same code is executed in all instances of the game (host and clients). To let the players to control only their ships, and not all ships in the game, we need to add an If condition in the beginning of the FixedUpdate method checking if this is the local player (if you’re curious on how the game would work without this If condition, try removing it. When moving a ship in a screen, all ships should move together).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class MoveShip : NetworkBehaviour 
{
    [SerializeField]
    private float speed;

    void FixedUpdate () 
    {
        if(this.isLocalPlayer) 
        {
            float movement = Input.GetAxis("Horizontal");	
            GetComponent<Rigidbody2D>().velocity = new Vector2(movement * speed, 0.0f);
        }
    }
}

Before playing the game, we still need to tell the NetworkManager that the Ship prefab is the Player Prefab. We do that by selecting it in the Player Prefab attribute in the NetworkManager component. By doing so, everytime that a player starts a new instance of the game, the NetworkManager will instantiate a Ship.

Setting the network manager player prefab.

Now you can try playing the game. The ship movement should be synchronized between the two instances of the game.

Game scene showing two blue space ships

Spawn Positions

Until now all ships are being spawned in the middle of the screen. However, it would be more interesting to set some predefined spawn positions, which is actually easy to do with Unity multiplayer API.

First, we need to create a new Game Object to be our spawn position and place it in the desired spawn position. Then, we add the NetworkStartPosition component to it. I’m going to create two spawn positions, one in the coordinate (-4, -4) and the other one in the coordinate (4, -4).

Spawn position object with a network start position.Start position object with a NetworkStartPosition component.

Now we need to define how the NetworkManager will use those positions. We do that by configuring the Player Spawn Method attribute. There are two options there: Random and Round Robin. Random means that, for each game instance, the manager will choose the player start position at random among the spawn positions. Round Robin means it will go sequentially through all spawn positions until all of them have been used (for example, first SpawnPosition1 then SpawnPosition2). Then, it starts again from the beginning of the list. We are going to pick Round Robin.

Setting the player spawn method to round robin in the network manager.

By now you can try playing the game again and see if the ships are being spawned in the correct positions.

Game scene with blue space ships farther apart

Shooting Bullets

The next thing we are going to add in our game is giving ships the ability fo shooting bullets. Also, those bullets must be synchronized among all instances of the game.

First of all, we need to create the Bullet prefab. So, create a new GameObject called Bullet and make it a prefab. In order to manage it in the network, it needs the NetworkIdentiy and NetworkTransform components, as in the ship prefab. However, once a bullet is created, the game does not need to propagate its position through the network, since the position is updated by the physics engine. So, we are going to change the Network Send Rate in the Network Transform to 0, to avoid overloading the network.

Also, bullets will have a speed and should collide with enemies later. So, we are going to add a RigidBody2D and a CircleCollider2D to the prefab. Again, notice that the CircleCollider2D is a trigger.

Bullet object with the physics and networking components.

Now that we have the bullet prefab, we can add a ShootBullets script to the Ship. This script will have as parameters the Bullet Prefab and the Bullet Speed.

Attaching the shoot bullets script to the ship prefab.

The ShootBullets script is also a NetworkBehaviour, and it is shown below. In the update method, it is going to check if the local player has pressed the Space key and, if so, it will call a method to shoot bullets. This method will instantiate a new bullet, set its velocity and destroy it after one second (when the bullet has already left the screen).

Again, there are some important network concepts that must be explained here. First, there is a [Command] tag above the CmdShoot method. This tag and the “Cmd” in the beginning of the method name make it a special method called a Command. In unity, a command is a method that is executed in the server, although it has been called in the client. In this case, when the local player shoots a bullet, instead of calling the method in the client, the game will send a command request to the server, and the server will execute the method.

Also, there is call to NetworkServer.Spawn in the CmdShoot method. The Spawn method is responsible for creating the bullet in all instances of the game. So, what CmdShoot does is creating a bullet in the server, and then the server replicates this bullet among all clients. Notice that this is possible only because CmdShoot is a Command, and not a regular method.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class ShootBullets : NetworkBehaviour
{
    [SerializeField]
    private GameObject bulletPrefab;

    [SerializeField]
    private float bulletSpeed;

    void Update () 
    {
        if(this.isLocalPlayer && Input.GetKeyDown(KeyCode.Space)) 
        {
            this.CmdShoot();
        }
    }

    [Command]
    void CmdShoot ()
    {
        GameObject bullet = Instantiate(bulletPrefab, this.transform.position, Quaternion.identity);
        bullet.GetComponent<Rigidbody2D>().velocity = Vector2.up * bulletSpeed;
        NetworkServer.Spawn(bullet);
        Destroy(bullet, 1.0f);
    }
}

Finally, we need to tell the network manager that it can spawn bullets. We do that by adding the bullet prefab in the Registered Spawnable Prefabs list.

Adding the bullet prefab to the network manager's registered spawnable prefabs.

Now, you can try playing the game and shoot bullets. Bullets must be synchronized among all instances of the game.

Unity Game scene with two blue spaceships and a bullet

Spawning Enemies

The next step in our game is adding enemies.

First, we need an Enemy prefab. So, create a new GameObject called Enemy and make it a prefab. Like ships, enemies will have a Rigidbody2D and BoxCollider2D to handle movements and collisions. Also, it will need a NetworkIdentity and NetworkTransform, to be handled by the NetworkManager. Later on we are going to add a script to it as well, but that’s it for now.

Enemy prefab with Mirror and Unity's networking components.

Now, let’s create a GameObject called EnemySpawner. The EnemySpawner will also have a NetworkIdentity, but now we are going to select the Server Only field in the component. This way, the spawner will exist only in the server, since we don’t want enemies to be created in each client. Also, it will have a SpawnEnemies script, which will spawn enemies in a regular interval (the parameters are the enemy prefab, the spawn interval and the enemy speed).

Enemy spawner object which spawns enemy prefabs.

The SpawnEnemies script is shown below. Notice that we are using a new Unity method here: OnStartServer. This method is very similar to OnStart, the only difference is that it is called only for the server. When this happens, we are going to call InovkeRepeating to call the SpawnEnemy method every 1 second (according to spawnInterval).

The SpawnEnemy method will instantiate a new enemy in a random position, and use NetworkServer.Spawn to replicate it among all instances of the game. Finally, the enemy will be destroyed after 10 seconds.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class SpawnEnemies : NetworkBehaviour 
{
    [SerializeField]
    private GameObject enemyPrefab;

    [SerializeField]
    private float spawnInterval = 1.0f;

    [SerializeField]
    private float enemySpeed = 1.0f;

    public override void OnStartServer () 
    {
        InvokeRepeating("SpawnEnemy", this.spawnInterval, this.spawnInterval);
    }

    void SpawnEnemy () 
    {
        Vector2 spawnPosition = new Vector2(Random.Range(-4.0f, 4.0f), this.transform.position.y);
        GameObject enemy = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity) as GameObject;
        enemy.GetComponent<Rigidbody2D>().velocity = new Vector2(0.0f, -this.enemySpeed);
        NetworkServer.Spawn(enemy);
        Destroy(enemy, 10);
    }
}

Before playing the game, we need to add the Enemy prefab to the Registered Spawnable Prefabs list.

Adding the enemy prefab to the network manager's registered spawnable prefabs list.

Now you can try playing the game now with enemies. Notice that the game still doesn’t have any collision handling yet. So you won’t be able to shoot enemies. This will be our next step.

Unity game scene with spaceships and green enemies

Taking Damage

The last thing we are going to add to our game is the ability to hit enemies and, unfortunately, to die to them. In order to keep this tutorial simple, I’m going to use  the same script for both enemies and ships.

The script we are going to use is called ReceiveDamage, and it is shown below. It will have as configurable parameters maxHealth, enemyTag and destroyOnDeath. The first one is used to define the initial health of the object. The second one is used to detect collisions. For example, the enemyTag for ships will be “Enemy”, while the enemyTag for enemies will be “Bullet”. This way, we can make ships colliding only with enemies, and enemies colliding only with bullets. The last parameter (destroyOnDeath) will be used to determine if an object will be respawned or destroyed after dying.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class ReceiveDamage : NetworkBehaviour 
{
    [SerializeField]
    private int maxHealth = 10;

    [SyncVar]
    private int currentHealth;

    [SerializeField]
    private string enemyTag;

    [SerializeField]
    private bool destroyOnDeath;

    private Vector2 initialPosition;

    // Use this for initialization
    void Start () 
    {
        this.currentHealth = this.maxHealth;
        this.initialPosition = this.transform.position;
    }

    void OnTriggerEnter2D (Collider2D collider) 
    {
        if(collider.tag == this.enemyTag) 
        {
            this.TakeDamage(1);
            Destroy(collider.gameObject);
        }
    }

    void TakeDamage (int amount) 
    {
        if(this.isServer) 
        {
            this.currentHealth -= amount;

            if(this.currentHealth <= 0) 
            {
                if(this.destroyOnDeath) 
                {
                    Destroy(this.gameObject);
                } 
                else 
                {
                    this.currentHealth = this.maxHealth;
                    RpcRespawn();
                }
            }
        }
    }

    [ClientRpc]
    void RpcRespawn () 
    {
        this.transform.position = this.initialPosition;
    }
}

Now, let’s analyze the methods. In the Start method, the script sets the currentHealth to be the maximum, and saves the initial position (the initial position will be used to respawn ships later). Also, notices that there is a [SyncVar] tag above the currentHealth attribute definition. This means that this attribute value must be synchronized among game instances. So, if an object receives damage in one instance, it will be propagated to all of them.

The OnTriggerEnter2D method is the one responsible for handling collisions (since the colliders we added were configured as triggers). First, we check if the collider tag is the enemyTag we are looking for, to handle collisions only against objects we are looking for (enemies against ships and bullets against enemies). If so, we call the TakeDamage method and destroy the other collider.

The TakeDamage method, by its turn, will be called only in the server. This is because the currentHealth is already a SyncVar, so we only need to update it in the server, and it will be synchronized among the clients. Besides that, the TakeDamage method is simple, it decreases the currentHealth and checks if it is less than or equal to 0. If so, the object will be destroyed, if destroyOnDeath is true, or it the currentHealth will be reset and the object will be respawned. In practice, we will make enemies to be destroyed on death, while ships will be respawned.

The last method is the respawn one. Here we are using another multiplayer feature called ClientRpc (observe the [ClientRpc] tag above the method definition). This is like the opposite of the [Command] tag. While commands are sent from clients to the server, a ClientRpc is executed in the client, even though the method was called from the server. So, when an object needs to be respawned, the server will send a request to the client to execute the RpcRespawn method (the method name must start with Rpc), which will simply reset the position to the initial one. This method must be executed in the client because we want it to be called for ships, and ships are controlled only by players (we set the Local Player Authority attribute as true in the NetworkIdentity component).

Finally, we need to add this script to both the Ship and Enemy prefabs. Notice that, for the ship we need to define the Enemy Tag as “Enemy”, while for the Enemy this attribute value is “Bullet” (you also need to properly define the prefabs tags). Also, in the enemy prefab we are going to check the Destroy On Death attribute.

Finishing off the player ship object.

Finishing the enemy prefab.

Now, you can try playing the game shooting enemies. Let some enemies hit your ships to see if they’re being correctly respawned as well.

Conclusion

And this concludes this tutorial! While small, we now have a nifty multiplayer game to work with. However, you don’t have to stop here! You consider improving this project by adding sounds, or maybe even making a procedurally generated map for more endless amounts of fun. Either way, this project is sure to make a great addition to any coding portfolio!

You can also choose to expand your Unity knowledge with online courses on other topics such as making RPGs, FPS games, and much more. For classrooms, Zenva Schools also offers a great selection of Unity courses suitable to classrooms and with expansive topics on other genres – including VR.

We hope you’ve learned a lot here, and we wish you the best of luck with your future game projects!

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

]]>
Free Course – Local Multiplayer Ready Player Controllers https://gamedevacademy.org/local-multiplayer-player-unity-tutorial/ Wed, 21 Jul 2021 01:00:28 +0000 https://coding.degree/?p=1216 Read more]]>

Start creating multiplayer, platforming shooters in Unity by first learning how to set up the all-important player character controller! You can also extend the material covered here by checking out the full course below!

Create a Retro Local Multiplayer Game

About

In this course taught by instructor Daniel Buckley, you’ll explore Unity’s Input System to detect actions from controllers and render players. You’ll start with learning input actions, action maps, scripting, and more – all in ways that you can easily extend for local multiplayer games. Regardless of your skill level, this course will help you get started with platformers and help you learn some quick tricks for getting your player up and running for your game projects!

]]>
An Overview of PlayFab for Multiplayer Games https://gamedevacademy.org/unity-playfab-tutorial/ Fri, 06 Dec 2019 01:00:18 +0000 https://gamedevacademy.org/?p=10527 Read more]]>

You can access the full course here: Player Authentication with Azure PlayFab

Setting up the PlayFab App

To begin, let’s go to the PlayFab website: http://playfab.com. If you have a Microsoft account, click Login, otherwise Sign Up.

Microsoft Azure PlayFab website

When you login, you’ll be taken to the Developer page. Here, click on the New Studio to create a new studio.

Azure PlayFab developer page

All we need to do here, is enter in a Studio Name. Then click the Save Studio button. This will redirect you back to the Developer page. Click on your studio to go to the Dashboard.

Azure PlayFab New Studio setup screen

The Dashboard is the visual interface between you and the database. We can view data about our players and navigate to many of the different databases. Feel free to click around and look at the different pages.

Azure PlayFab dashboard

In the next lesson, we’ll be hop into Unity and start to create our project.

Transcript

Hey everyone! In this lesson, we are gonna be going over basically what is Playfab and how can we use it in our games.

At its core, PlayFab is a backend for your game. And this is for stuff such as storing play information like player accounts. Maybe play information as well. And all sorts of stuff that you want players interacting with each other, for example, maybe trading, selling items, all the sort of stuff that you won’t have directly on the client-side. Something that you want in the back end so when the player turns off the game and turns it back on, that information will still be there.

Traditionally you would have to do it pretty much all on your own. You would have to create your own databases and maybe set up servers and create all the backend code that can interact with your game that the client has. But in this case, PlayFab has that all set up for us and really takes away the stress of wondering how to do it and if you’re doing it in the right way. Taking into consideration stuff such as authentication and making sure that there can’t really be any abuse from the client-side of things.

So, let’s actually look at a bunch of different features here inside of PlayFab. Right now, I’m on the PlayFab website which is just Playfab.com and I’m gonna go up to features here and game services. And here we can have a look at all the different features that PlayFab has.

There’s player authentication and linked accounts. You can create player accounts with a user name, password, email. You can also do it automatically so that the player doesn’t really have to enter any information, it just automatically knows what device they’re on and creates an account for that. You can also log in with Facebook, Google, all those other sort of things that you see with games as well.

There’s also leaderboards, you can set up leaderboards, ranking players based on pretty much anything. You can send push notifications and emails to your players. Maybe if you’re informing them about a new service or a new update on the game. Of course, you can store and manage player data. Any sort of data, really, that you’d want you might wanna store how much gold or something a player has or certain features that you need for a game. Maybe other players also want to be able to access information from other players.

Multiplayer services as well. Now, these multiplayer services, this isn’t really working with Unity at the moment so we’re not really gonna be focusing on this.

There’s commerce which is a big part of PlayFab. This involves having items, players can have inventories that can hold items, you can trade items between players. In-game characters, allow you to create separate characters for your player maybe in your game. Players can play as different classes or different sort of things and this is how you do it. This is very similar to the way you can store individual information for each character, individual inventories, all that sort of stuff.

And finally, you can create and track virtual currencies. This can be used to purchase items from the store. You can also trade currency between players, you can hand it between each other. You can also make it so that players can even buy this currency through in-game purchases. So really, this is just a list of all those sorts of services that you can have in your game and PlayFab makes it so we don’t have to do this all by ourselves, we don’t have to set up the player authentication and logging in, we don’t have to set up all the item stores, all the inventory systems, all that sort of stuff. It is already created for us here on Playfab and all we need to do in Unity is just connect to the API and create calls between it.

PlayFab also has both a free and paid plans. Very similar to Unity with the free plan you have access to quite a lot of the stuff. If we just scroll down here and click on compare all pricing tiers, we can see that all the stuff we really need such as in-game commerce, player profiles, content management, that all comes with the free version of PlayFab.

Now, it’s only really necessary to get the paid plans if you do wish to have access to these professional features. Or if you get over 1000 monthly active users. So, these are unique users each month. If you get over 1000 of those, then you are required to get one of the paid versions of PlayFab. Very similar to Unity how if you get over $100,000 in revenue, you need to upgrade to a pro plan. But for now we can just use the free plan, we can just use the essentials plan right here. As it really is just all the stuff we need right here.

So now, what we’re gonna do is let’s actually login to PlayFab or sign up. If you do have a Microsoft account, you can just login – but we can also sign up if you wish. And once you do that you’ll be taken to the developer page here. I’ve already got a game and studio here set up. But what we can do is just click on this new studio button right here and this will create us a new studio.

Now, the name doesn’t have to be unique or anything like that in general. This can just be whatever you want, just something that you can identify it with. So here I’m just going to call this PlayFabCourse and the authentication provider is going to be Playfab. We can click on save studio. And it will create our new studio here.

So here I can see PlayFabCourse right here. Let’s click on my game. And here we are inside of PlayFab. Now, we land here on the dashboard and there’s a bunch of information. Now, you can’t really see anything because there isn’t, well, no one’s actually connected to this API. No one’s connected to our game yet. So we’re not gonna see any information here. But we can see stuff such as unique users, the API calls, a bunch of other stuff as well. Logins, new users, purchases. This is very useful if you just want to have a front end, direct sort of view on how your app is going perhaps.

There’s also other information down here such as reports but what we wanna be focusing on is the left-hand side here which has a bunch of different tabs that we can select and look at. You have players, economy, leaderboards, multiplayer, groups, content, automation, analytics, add ons, settings, admin, and help.

Let’s click on the players tabs and have a look at this. This here is going to be a list of all our players. Now, whenever a player creates a new account, they’ll be popping up right here so we can have a look at all the players who are in our games. And we can even go into their player accounts and see their individual information. What sort of information are they storing, what sort of items are in their inventory, and yeah, a bunch of other information that we want to save to the cloud here for later use when they maybe log in again or if other players wanna access information about other players.

We then have the economy and here we can create something called the catalog. Now, a catalog is basically a container or a list of item, categorized items perhaps. So let’s just say you have a shop, you could create a new catalog here for that shop and in there you would list a bunch of different items that sort of relate to that catalog. With those items you can give it a unique ID, a display name, maybe even a price. And other things as well such as is it tradable, is it consumable, is it stackable? All the sort of stuff that we want to know when we are implementing them into our game.

Over here in the currency tab up top. We can create new currencies, so in your game you might want to have multiple as well. You can create as much as you want and you can use those individual currencies for purchasing the items and maybe just giving them to other players as well. There’s leaderboards which of course allow you to create leaderboards based on any sort of ranking. Multiplayer, we’re not gonna be looking at that since that is not really implemented into unity yet.

Groups, allow you to create groups for players. Maybe if you wanna have parties or clans, you would create a group for that party or clan and just add the respective people to that. The groups also allow you to store data in them or share data between the players in the group. Content here, this is just pretty much like global sort of information here in the title data.

File management, you can upload files to read. Email templates, push notification templates. Maybe you wanna send your users information about a new update, you could do it that way. In automation there’s something called the cloud script.

Now, when you are setting up stuff and making API calls inside of Unity, you don’t always wanna do everything from Unity. Because, let’s just say you want to access information about another player. Let’s just say you wanna get a player’s inventory because you want to be able to maybe see what items they have. Now, if you were to make an API call to the server from the client app to get the player’s items, then that could actually be abusable. Maybe if someone gets into your game code, maybe figures out a loophole around it. Then they’d actually be able to access information from the player, not just from the inventory.

So, this is where the cloud script comes in handy. You can send a call to the cloud script and on there in the cloud that is where all the game information of the player is and it sends back just the specific information that you need. We won’t be using that in this course, but it is something that is very useful in the PlayFab API.

Okay, that is about it for now. This is just a very brief overview of the dashboard here. There’s, of course, a lot more settings and a lot more things to look at and learn, but for now, we’ll keep it at that. In the next lesson, we’ll actually begin to set up our unity project, implementing the PlayFab plugin and setting that all up. So I’ll see you all then in the next lesson.

Interested in continuing? Check out the full Player Authentication with Azure PlayFab course, which is part of our Multiplayer Game Development Mini-Degree.

]]>
A Guide to Tilemaps & RPCs for Multiplayer Games https://gamedevacademy.org/unity-rpc-multiplayer-guide/ Fri, 20 Sep 2019 15:00:13 +0000 https://gamedevacademy.org/?p=10362 Read more]]>

You can access the full course here: Turn-Based Game – Multiplayer Projects

Part 1

Folder Structure

In the Unity project, let’s setup our folders in the Project window. Create the following folders:

  • Resources
  • Sprites
  • Scenes (if you don’t have it)
  • Tilemap

Scenes

Now we need to create our two scenes: Menu and Game. In both scenes, we need to change the camera from a 3D one, to a 2D one.

  • Set the Projection to Orthographic
  • Set the Clear Flags to Solid Color
  • [Game scene camera] Set the Size to 4 (not seen in image)
  • [Menu scene camera] Set the Background color to a muddy-green (not seen in image)

Unity Inspector for the Camera component

Tilemap

In the Game scene, we want to setup a tilemap in order to create our background. Right click the Hierarchy and select 2D Object > Tilemap. You should now see a grid appear in the scene view.

Unity scene with Grid added

In order to paint on the tilemap, we need to open the Tile Palette window (Window > 2D > Tile Palette). Then click on Create New Palette and call it whatever you want.

Unity Tile Palette window

With that created, we can now drag in the grass sprite. It will ask you to save the asset.

Unity sprite added to tile palette

Now we can select the paint brush icon and the grass sprite and begin to paint. Cover the bounds of the camera with tiles.

Unity scene with tile painted on tilemap

In order to create an actual “grid” appearance, we’re going to change the size of the grass sprite. Select the sprite and set the Pixels Per Unit to 66.

Unity tile import settings in Inspector

We can then change the Background color of the camera to whatever the grid lines should be. I’m going to choose a dark green so that it blends in with the background but still stands out.

Unity Inspector with camera background color picker

Sorting Layers

Let’s now create some sorting layers as we are working with 2D. Click on the Layers dropdown in top right corner of the screen and select Edit Layers… Here, we want to add 3 sorting layers.

  • Background
  • Unit
  • UI

Select the Tilemap object (child of Grid) and set the Sorting Layer to Background.

Unity Tilemap Renderer sorting layer in Inspector

Part 2

Remote Procedure Call (RPC)

Remote Procedure Call (also known as an RPC), allows you to call functions on other player’s computers. If you shoot a player on your computer, you would send them an RPC, telling them that you hit them. You can tag a function as receiving RPC’s, by adding the [PunRPC] attribute. As well as being able to send an RPC directly to a specific, you can also send these to a group or types of players in different ways. These are known as RpcTargets.

  • All sends the RPC to everyone in the room, calling it instantly on the sender’s computer.
  • AllViaServer is the same as All, but doesn’t call it instantly on the sender’s computer.
  • Others sends the RPC to everyone but the sender.
  • MasterClient sends the RPC to the master client.
  • AllBuffered is the same as All but caches the call for new players who join the room.
  • AllBufferedViaServer is the same as AllViaServer but caches the call for new players who join the room.
  • OthersBuffered is the same as Others but caches the call for new players who join the room.

PhotonView

PhotonView, is a component which identifies an object across the network. How does Photon know which objects are the same thing across different player’s computers? GameObjects have an instance ID, but these are randomly generated and will be different on other computers. So a PhotonView, makes a connection to the network and is also required in order to receive RPC’s. Things like the network manager, players, units, game manager, etc. Anything that interacts with the network, needs a PhotonView.

 

Transcript 1

Welcome, everyone. My name is Daniel Buckley, and I’ll be your instructor for this course. Let’s have a look at what we’ll be making.

We are going to be creating a 2D top-down turn-based strategy game using Unity. This, of course, is going to be multi-player, as well, and it is going to be a one V one game. As you can see here each player can take their turn to move their units and, in a turn, each unit can either move or attack. Each unit also has a set movement distance and a set attack range which is the maximum for that unit. And also when you click on a unit you can see its statistics and as you can see in here the movement the units are moving towards each other and where they will begin to attack. Okay.

Now let’s have a look at how we’ll be creating this. We will be using the Photon Unity Networking framework. This is a free multi-player framework for Unity, and since Unit is now deprecated, this is probably the number one solution. We’ll be creating some units. Each unit will be able to move and attack and each unit also has a max movement and attack distance and they can choose to either move or attack each turn. And as you can see here we have two types of units and really all this involves in creating two types of units is just to change the properties inside of the inspector, just changing the sprites and changing the values for the movement, attack, and speeds and such.

In order for two players to get together to play a game, we will be creating a lobby system. This will involve the player entering in a name and then clicking play game, and what this will do is it’ll either create or join a room. If there are no rooms available, the player will create a room and wait for another player to join. If there is a room available, it’ll pick a random room and join that one.

This will all be done using Unity’s UI system. We’ll be working with canvases, text elements, buttons, input fields, and more. As you can see here, we have quite a few different UI elements, and we’ll be going over each of them explaining how they work, how we can change them, how we can connect them up to a script, and also with anchoring and positioning on the screen.

Zenva is an online learning academy of over 400,000 students. We feature a wide range of courses for people who are just starting out or for someone who just wants to learn something new. The courses are also very versatile. You can choose to follow along with the included project files or even follow along with the included lesson summaries. So you can choose to watch lessons, read them, follow along, or really whatever you want.

Thank you very much for watching. Now let’s get started on our project.

Transcript 2

Welcome back, everyone. In this lesson we are going to be setting up our project.

First of all, let’s set up our actual project folder structure. So down here in our project window, what we want to do is create a new folder, and this folder here is going to be called our Sprites. And this, of course, is gonna hold all of the sprites for our game. Now, we can also create another folder, and this folder is going to be called Tilemap. Because for the background of the map, we are just gonna be using Unity’s Tilemap tools to do that.

And what else we need is one more folder called Resources. And Resources is where we’re gonna be storing all of our Prefabs that we’re gonna spawn in. And the reason why we don’t- not resource, resources – and the reason why we don’t put this in a Prefabs folder is because Resources is a folder that Unity can actually identify and access. And the reason why we need that is because Photon to instantiate an object, you don’t actually instantiate it by a Prefab, you instantiate it by Prefab path, in the Resources folder. So everything that you want to instantiate over the network, you need to put in the Resources folder. So that’s what we’re doing there. Okay.

Now let’s go inside of our Sprites window here, in our Sprites folder. And what we need to do is import a few of our Sprites. The first one is going to be our cursor selector. This is gonna be what appears on the grid to show you which tile you’re selecting. We also need our- we also need our soldiers. This is gonna be one of our units. And then we also need our tanks. This is gonna be our other unit.

We also then need our tile, which is going to be the grass tile that we’re gonna be using. You can choose to use whatever tiles you want. And finally we need a white square, and this is gonna be for the health bar. Now with these five assets here, these are actually using free artwork by Ken, who actually has a wide range of free assets on his website. There will be a link down in the lesson summary to that.

Okay, so first of all what we need to do is actually convert these sprites into something we can use. ‘Cause right now, they are actually set as material. Not materials, but actually as normal textures. But we wanna convert these to Sprites. So let’s select all of these here, and up here in texture type, we want to change this from default to Sprite 2D and UI. Now you can click on the apply button and you should see they now fit to their proper aspect ratios.

Okay, but there are a few things we also need to do, and that is changing the pixel ratio. For the tile grass one here, what we need to do is change the pixels per unit here to 64. And that is because there is 64 pixels horizontally and vertically here. And what we’re gonna do is we wanna make it pretty simple, we wanna make it so that this tile here is one by one unit’s large. Just makes it much easier to work with. So we’ll click apply.

And we actually wanna do the same thing for the soldier and the tanks. So we’ll select all those, change their pixels per unit to 64. Hit apply as well. And for our cursor selected, what we want to do is also do this for 64 as well. Because as you can see down here, this is also a 64 by 64 image, so we’ll do that too. Hit apply. And that should pretty much be it.

Now what we can do is actually go create our scenes. So in our scenes folder here, it should be already pre-built by Unity. We can click the sample scene here. And create a new scene and we’ll call this one Menu. And then we can also create another scene and this one we’ll call Game. Now let’s open up the Game scene. I don’t save the Sample scene. And inside of here what we want to do is create our Tilemap. So, to create a Tile map inside of Unity, which is basically just a bunch of tiles that Unity meshes together in one large sprite.

Actually first of all what we want to do is change our main camera and put it into more of a 2D mode, ‘Cause right now this camera is set for 3D. So what we can do is select the camera and change the projection here from perspective over to orthographic. And what this is, this basically is the difference between capturing depth with perspective, which is what you’d use for 3D. Objects that are further away become smaller. Where as we want orthographic, which means that no matter the distance away the object is, it maintains the same size.

With that then we can also change the clear flags from Skybox to Solid Color. And this makes it so the background is a solid color. We’ll be getting into this a bit more detail later on when we actually get our tile set up, but for now we’ll just leave it for this blue here. And everything should be all right.

So, to create our tiles what we want to do is right-click on hierarchy, go 2D object, Tilemap. Now if we go to the Scene view now you’ll see if we click on this 2D icon up here, this will take us into 2D mode. We should see that if we clicked our grid, we now have a bunch of little squares that we can draw into. But in order to draw in these squares, we need to open up the Tile Palette window.

So let’s go to Window, let’s then go down to 2D, Tile Palette. And this will open up this window here which allows us to create a new palette. Let’s actually do that now. So click on Create New Palette. And we’ll call this one here TurnBasedBackground. Let’s click Create. It’ll ask us to save it somewhere, and we want to save this inside of our Tilemap folder here. Select that folder, and it’ll create it.

Now in order to actually add tiles, let’s go our Sprites folder, and drag in the Tile grass one. It’ll ask us to create it as an asset. We’ll go back to our Tilemap folder and just click save. And there we go. We now have this tile that we can draw with. So if we go into the Scene view here, we can begin to actually draw. If you have this brush here selected, this is the brush tool, we can then start painting.

But you might notice that this is fairly large, and we actually wanna reduce the size of this, of the map. Just so it’s a lot smaller. You can choose of course to make it larger. We’re gonna make it a bit smaller now, so it’s a lot more concise and we can get into battle quicker.

So we’re gonna click on the main camera, and change its size from five down to four. The orthographic size is basically how much, how many units are from the center of the camera to the top and bottom of the frame. So you can see they’re right now four tiles from the top to bottom. So it’s eight in total in the height. And what I want to do is select our grid again, and let’s just fill this in with the green tiles. There we go, it’s finished. I had to put the tile out here a bit more, since they did kinda cut over the edge of the camera.

And also with this game, we are gonna be making it for a 16 by nine aspect ratio. You can, of course, choose to make it whatever aspect ratio you want, but 16 by nine, that’s good for 1080p screens. Pretty much any sort of monitor will be able to run this in 16 by nine.

And yeah, so if we go into Game view now, we can see that our scene is filled with these green tiles, and we’re ready then to start making our game.

Apart from this though, what we need to do is we can close this Tilemap, Tile Palette window off now. And what we want to do is actually go to our Menu scene, and we’re just gonna set that up for 2D as well.

So, we’ll save the Game scene. Go to the Menu scene. And if you look in the Game view, you can see that once again this camera is still built for 3D mode. So let’s change that from perspective to orthographic. Skybox to Solid Color. And let’s exchange this background color to something, we’ll change this to like a green. To show that it’s sort of part of this military sort of themed turn-based game.

And speaking of backgrounds, let’s actually go back to our Game scene. And you might want to notice that there is no grid, because in this sort of game that’s grid-based, you might want a grid here that actually divides the tiles up so you can see exactly how many tiles away you are from something. And to do that what we’re gonna do is click on, not our grid here, let’s go to our Sprites. And what we can do is actually change this pixels per unit here from 64 over to something for example 65. Click apply. And it makes the Sprite slightly smaller, to show that it’s visible like that. Let’s actually change this from 65 to 66, opps 66, just so the lines are a bit more bold like that. There we go.

And what we can do now is actually change the main camera background from blue to whatever color you want the lines to be. You can have them black or white, but for us I think we’re gonna go for a dark green. So it still sorta blends in with the environment, but it’s still easy to tell where those lines are. Yeah, something like that I reckon.

Something else we need to do is also add in some sorting layers. ‘Cause since we’re working with 2D Sprites, we need to tell Unity which Sprites should be rendered over specific other Sprites. Now to do that let’s go up to the Layers button up here and click Edit Layers. Now in here we can open up the Sorting Layers window here, and we can start adding in some sorting layers.

So we can click on the plus here, and we’re gonna enter in UI. We’re gonna add another one, we’re gonna add in Background. Then we’re gonna add in Unit. And let’s rearrange these now so they are actually in the correct order. So we’ll have UI right the front, and then we’ll have Background at the back, and Unit here.

Okay. So with that done we can now actually set our grid to have the background Sprite, have the background sorting list so we can click on the Tilemap here, and then we can go to where it says Sorting Layer, and we’ll change that to Background.

Okay so that’s pretty much it for setting up our project. We’ve imported all the Sprites we need. We’ve got our Menu scene and our Game scene set up and ready to go to start creating our turn-based game. See ya, I’ll see ya’ll in the next lesson where we start to create our network manager.

Transcript 3

Hey everyone, in this lesson we are going to go over two important concepts before we continue on with our project. And these two different concepts are going to be very important in actually being able to relay information over from one computer to another inside of Photon.

The first is Remote Procedure Calls, or RPCs. RPCs allow you to call functions on other player’s computers. So just like on your computer, when typing code you would just go FunctionName, and then brackets. That is how you will call a function, for example.

But let’s just say you wanted to call a function, for example, you have an enemy and you wanna damage them and you wanna call the take damage function on them. Well, normally you would just call their take damage function, but in order for that player to actually have that function be called on their computer, you need to do something. You need to call an RPC, and here is how we can do it.

There’s two different ways to do an RPC. The first one is you go PhotonView, we’ll get to that soon. Dot RPC, and then in brackets, you have the name of the function as a string, and then comma, and then you enter in the player you wanna do, you want to send it to. And this is a Photon player. Remember where you had the player class, which is the Photon Player? And that is the person we want to send this to. And then you can have some parameters there if you do have parameters.

The other way, though, is sending it to an RPC target, and this is not extending it to an individual person, but sending it to a group of people or a specific group of people in a certain way. Here are all the different RPC targets. We have All Via Server, Others, Master Client. All Buffered, All Buffered Via Server, and Others Buffered.

All executes the function instantly on your computer and sends that function out to everybody else inside your room to call that function on their computer. All Via Server sends that function call up the server, and then from the server it tells everybody, including you, to call that function. Others sends that function to everybody else but you.

Master Client sends that function to the Master Client. And then we go into the buffered. Now, what buffered means is that it will actually cache that function call, so what it means is that, let’s just say you call the change color function, for example, just a hypothetical function, and it changes your color to blue. You could call that with All, for example, but what if somebody was to then join the game after you call that? You join the game and, for them, for you everyone’s blue, yet for them nobody’s blue.

The way to have a function call for them that has already been called is to set it in All Buffered. And what this does is cache that function for when new people join the room – it will call that function on their computer. So you’ve got All Buffered, and then you’ve got All Buffered Via Server, and then you’ve got Others Buffered, okay?

So that’s pretty much the gist of RPCs. We’ll get into those in more detail when we start actually using them. But for now, this is just a brief overview on what they do and how we are going to used them in the project. And we are going to use them quite a lot in the project.

Okay, so let’s move on to our next concept, which is the PhotonView. Now a PhotonView is a component which identifies an object across the network. This, if you want to call an RPC to an object, that object needs a PhotonView. Because in Unity, at the moment, how does Photon know which objects are the same across the network?

Each game object does have its own instance ID for the game object, but that is randomly generated and it is actually different, of example, if you had two instances of the game launched, and you had to spawn in an object, that object would have a different instance ID from the other. So at the moment, there is no real way for Photon to know which objects are the exact same across different players’ computers.

And the way you do that is with a PhotonView component, and more specifically, the View ID of that Photon View. So each object inside the world has a unique UID, each player, the network manager, the game manager, the menu, all that sort of stuff, each has its own unique UID. So that Photon, when you send an RPC to that object from across the network, it knows exactly where to send it.

And there’s also different types of PhotonView extension components, for example. You can see that there is an observed components list that you can add stuff to, and what we’re going to be doing is, for our units, we want to be able to actually sync the position of these units across the server.

So when you click on a unit and move them, we want that movement to not only, you know, of course, it’s gonna be moving on your screen, but how are we gonna tell other computers, other people in the room to move that object, as well? We are going to be using something called a Photon Transform View, and what this does is, if you attach it to an object, that means that whenever that object moves, that position, or rotation, or scale will be updated across everyone’s computers automatically, instantly. And it also adds some smoothing, as well, so it’s not jittery.

That just prevents – that just doesn’t require us to do lots of code where we’ve gotta send the new position, receive it, and then serialize, not serialize it, but actually then lure it between your position and the new position. That’s what you used to have to do with networking, but now there’s that component, which makes it much easier. And we’ll get into that in more detail, of course, later on when we get to it. And of course, when we start using our PhotonViews, we’ll get into that in more detail, as well.

So for now, that’s just the brief overview of what an RPC and a PhotonView is. For sure we’ll be using these quite a lot throughout the project, as they are really the core of making a multiplayer game inside of Unity and being able to actually transmit information and Sync up value between computers. So yeah, I’ll see y’all in the next lesson when we actually begin on using these PhotonViews and RPCs.

Interested in continuing? Check out the full Turn-Based Game – Multiplayer Projects course, which is part of our Multiplayer Game Development Mini-Degree.

]]>
Create a Unity MMORPG Map with Tiled https://gamedevacademy.org/unity-tiled-mmorpg-tutorial/ Fri, 16 Aug 2019 15:00:17 +0000 https://gamedevacademy.org/?p=10285 Read more]]>

You can access the full course here: RPG – Multiplayer Projects

Part 1

Setting up the Project

Before we begin, let’s first set up our folders and scenes. In the Scenes folder, delete the default SampleScene. Then create 2 new scenes: Menu and Game. While we’re at it, let’s also add these to our Build Settings screen (File > Build Settings).

Unity Build Settings with Game scene added

Let’s now create the rest of our folders. Create the following:

  • Animations
  • Prefabs
  • Resources
  • Scripts
  • Sprites

All the sprite sheets are included in the project files. If you wish to download some other free sprite sheets though, you can do that here: https://kenney.nl/assets?q=2d

Scene Setup

Let’s now go to our game scene and select the camera. We need to change it from a 3D camera, into a 2D one.

  • Set the Projection to Orthographic
  • Set the Clear Flags to Solid Color

Now we can go to the menu scene and do the same thing. This time though, let’s change the background color.

  • Set the Background color to green/blue

Tags and Sorting Layers

At the top right of the screen, select the Layers drop down and click on Edit Layers…

Unity Layer windows with Edit Layers selected

Create the following tags and sorting layers:

Tags

  • Enemy

Sorting Layers

  • BG
  • Pickup
  • Enemy
  • Player
  • UI

In the next lesson we’ll used Tiled to create our tilemap and import it into Unity.

Part 2

Tiled

Tiled is a free software which allows us to easily create tilemaps. Go to https://thorbjorn.itch.io/tiled and download the Tiled Map Editor.

Tiled Map Editor download page

Once you download and install it, you should be able to launch the program. Select New Map…

Tiled opening screens with New Map button selected

Set the Width and Height to 30, then click Save As…, create a new folder in the project called Tilemap and save it there

When in the editor, we need to import a tile set. Click on the New Tileset… button.

  • Set the Width and Height to 32
  • Set the Source to the background image in the project

Tiled New Tileset creation window

We now need to create 2 layers. One for the Background (tiles that we can walk on) and one for Collision (tiles that we collide with).

Tiled Layer window with Background selected

Now just create any sort of map you wish.

2D Map made with Tiled

Now export both the map and tileset into the Tilemap folder.

SuperTiled2Unity

SuperTiled2Unity is a free Unity asset which converts Tiled maps into the tilemap format Unity uses. Download it from https://seanba.itch.io/supertiled2unity

This will download a .unitypackage file which you can just drag into the project window and import the asset.

Select our .tmx tilemap and:

  • Set Pixels Per Unit to 32
  • Enable Tiles as Objects (not see in image)

Click Apply. Do the same for the tileset.

Unity with Tiled map imported

Now we can drag in the .tmx tilemap file into the scene.

  • Set the Position to -15, 15, 0

Unity Transform component for tiled map

Next, select all of the collision tiles and add a Box Collider 2D component to them.

Unity 2D Box Collider component added to tilemap

 

Transcript 1

Hello, everyone. My name is Daniel Buckley, and I’ll be your instructor for this course. Let’s have a look at what we’ll be making.

We are gonna be making a multiplayer RPG game inside of Unity. As you can see, we have a lobby system, and then when the two players spawn inside the game, you can see that they both sync their positions up. We also have a chat box that the two players are typing in right now. And outside here, there are enemies that do spawn by spawners. You can defeat them, and there is gold to pick up after defeating them. So, let’s see all the different types of things that we are gonna learn in order to create this game.

First of all, we are gonna be using the Photon Unity Networking Multiplayer framework. This is a free multiplayer framework available from Unity. And since the deprecation of Unit, this is pretty much the most popular and main networking solution that most people use inside of Unity.

We’re gonna be creating a player controller. The player will be able to move, attack, pick up gold, heal, and, when they die, will wait a few seconds and then they’ll respawn at a random spawn point. As you can see, the player can also attack enemies with a little attack animation, and they have health bars above their head with their names, as well, which that’ll all be done, as well. We’ll go through how to do that – how to set up the UI for that.

There are also pickups. These pickups will be both dropped when enemies die, and they will also be positioned around the world, if you want. These can be really whatever you want. We’re gonna be designing them around health pickups and gold pickups.

And another feature we’re gonna be creating is a chat box. This will allow players to chat to each other in the game. When they type in a message, it will be synced across the entire network. So all players will see that message pop up instantly, along with the player name and their message.

For the menu, we’re gonna be creating a lobby system. This will allow the players to enter in a PlayerName, then either create or find a room. If you create a room, you’ll be sent to the lobby where you can wait for more players to join. And if you go to Find a Room, you’ll be taken to the lobby browser, where there will be a large list of all the different rooms that you can join, showing the room name, as well as how many players are currently in there. And then when all the players are in the lobby, you can see who is in there and then you can start the game. We’ll be doing all this with Unity’s UI system. Unity has a very good built-in UI system that we’ll be using. We’ll be talking about canvases, text, buttons, input fields, sliders, all the different sorts of UI elements. We’ll be using a wide range of different ones.

So yeah, Zenva is an online learning academy with over 400,000 students. We feature a wide range of courses for people who are just starting out, or for someone who just wants to learn something new. The courses are also very versatile, with video course that you can follow along with the included project files. There are also lesson summaries that you can choose to read through, if you wish. So, with all that said, let’s get started on our project.

Transcript 2

Hey everyone and welcome back. In this lesson we’re gonna be setting up our project. We’ll be setting the folder structure and importing some assets that we need.

First of all, let’s go down to our folders here. At the moment we’ve got out Photon folder and the default scenes folder that you get when you create a new Unity project. Let’s start with our scenes folder. Let’s go inside there, and we’ll just delete this sample scene here. Let’s create two new scenes, we want to create a new scene called Menu for the menu. And then another scene called game, where the actual gameplay will take place.

While we’re here actually, let’s add these to our Build Settings. Let’s go up to File, Build Settings, and let’s add these scenes in the build. Layout our idea, just so that we don’t have to do that later on and if we forget to. Put the game in and then we will put the menu above since we do want to launch into the menu scene.

Once we’ve got that done, let’s now go back to our assets folder and create the rest of our folders. Let’s create a new folder here and we’ll just call this one animations. As we do need to have an animation for the actual attack when the player attacks. If you do want to make anymore custom animations, you can just put them in here.

Okay, the next folder we want is Prefabs. This is going to be stuff like all of the non-network required Prefabs. I’ll explain that a bit later. Along with the Prefabs folder we need the Resources folder, and this is where we’re gonna be putting in all of the Prefabs that we need that are going to be spawned over the network. Again, I will explain this later once we actually get into creating these prefabs. Okay, we got that. Now we need a Scripts folder to store all of our scripts.

And finally we need a folder called Sprites. Sprites and let’s actually open the sprites folder because we need to import a few different sprite sheets while we’re here. We’ll open this up. There is going to be three included sprites, three included different files. In the project files that you can download – or you can choose to use your own. Actually, there is four, but we’re only going to import three; and we’re going to be using the other one later on, once we actually do our tilemap.

The first one we’re adding in is just a white square. The reason we need a white square here is for when we have the health bars. We’re not going to be using a slider, instead we’re just going to be using a image with a specific fill amount. In order to do that you need to have an actual sprite, you can’t just set it to none. We’ve got this here, let’s go up to our texture type. Change that from default to 2D and UI. Then click on apply. Just like that.

A second we need is the characters sprite sheet. These two sprite sheets we are going to be implementing in next are all free assets. They’re public domain sprites that you can use. With this we just want to go up here and change the texture type again to 2D and UI here, click on apply. And actually we also want to change it from the sprite mode from single to multiple. Then what we can click apply again.

Then open up the sprite editor here, and inside of the sprite editor we can actually individually cut these out. Now we can do that by hand but it will take some time. So what we can do is click on slice up here. Make sure it is on automatic. And then click on slice, just like that. As you can see they’re all automatically sliced up, now like so. We can click on apply. Wait for that to go, it might take a while since there is quite a lot of different sprites here. So it might take some time, there we go. Then we can click on the X.

What we want to do now is actually change the pixels per unit, because at the moment it’s 100. If we were to drag this into our project, for example, once we set it up with all the character and all that. We’ll see that this is a very small sprite, and the reason for that is because we need to set the pixels per unit to however many pixels we want in one Unity unit. These characters here are about 16 by 16. And since we want the character to fill up the whole tile. We’ll set the pixels per unit to 16, then click on apply.

Okay, with that done, we can drag in our next sprite sheet which is items. In here we can go click on that. We can change it from default to 2D and UI. We can click on apply. We can the change single to multiple, apply that again. Then click on sprite editor and do the exact same thing. We can go slice, set that to automatic, click on slice. Wait for it, yep there we go, got all our sprites here.

We’re not going to be using all these, really we’re just going to be using the heart and a couple of these gems to have as treasure. Again you can choose what sort of sprite that you want. We’re just going to be using those though so we can click on apply. Takes some time since there are quite a lot of sprites in this sheet. There we go, we can click on the X now. And we have all of our sprites in the game – actually no, first thing we need to do is click on the items here and change the pixels per unit from 10 to 21, as that is how many pixels there are per tile on this sprite sheet. So can click apply. Wait for that to do it’s thing and there we are, we are finished.

Now what we need to do is, we’ll just set up the cameras and that for the different scenes. If we go to our scenes folder, we will open up the game scene first of all. Don’t save the sample scene. Inside of here, we want to change our main camera from perspective to orthographic since we are working with 2D. Orthographic is what you would use as it doesn’t capture depth, where as perspective objects that are further away are smaller and closer up they are larger. Where as orthographic – it doesn’t matter the distance between objects, they are all the same size.

Here we can change the size of the camera here, but we will just keep that at five for now. We can also change the background since we don’t really want a skybox since it is going to be a side-on view. And it might look a bit weird. So we can click on here and go solid color instead, and I reckon we can just keep it like this for now. We can change this color to something else later on, but we will just have this for now.

Now we can go to our menu scene, we’ll save the game scene. And do the exact same thing: change the camera from perspective to orthographic, and we’ll change skybox to solid color – and for this we can actually set a color that we want for the menu. So whatever you sorta want for your menu scene, we can maybe have a green like that. There we go.

Now something else we want to do is also add in our tags and sorting layers that we’ll be using. To do that, we can go up here to the layers button here and just click on edit layers. In here will pop up with a list of what we can select, so let’s open up our tags and let’s add in a new tag. Click on the plus here. The tag we want to enter in is enemy. Now we already have a player tag, Unity already has the player tag pre-built into the editor. So we just need to add the enemy tag there and that’s, of course, is gonna be on our enemies tagged as them.

Then we can go on to our sorting layers here. What we want to do is we wanna create a bunch of short sorting layers. What these are, these basically decide which sprites get rendered on top of other sprites. Of course, we want the background to spawn right at the back, we want the UI to be spawned right at the front. We want the players to be spawned on top of the terrain but behind the UI. We will create a few of those.

First one, let’s create is going to be BG for background element. Then we will create another one here, this is going to be pickup for all of our pickups. Then we will create another and this is going to be called Enemy. The next is going to be our Player and then finally we have our UI. This is the order of how the sprites are going to be rendered.

Save that and that is our project set up pretty much done. In the next lesson, we will start to actually set up our tilemap using Tiled and then import it into Unity using Tile TNT! See ya!

Transcript 3

Welcome back everyone. In this lesson, we are going to be creating an actual map using Tiled. And Tiled is a free software which is pretty popular among many of the 2D map makers, and what it allows us to do is set up a tileset and pretty much just paint in the tilemap. And along with Tiled, Tiled Map Editor, we’re also going to be using Tiled2Unity – actually SuperTiled2Unity – which is able to then take this tilemap and convert it into something that can be used inside of Unity. So yeah.

We just wanna go on itch.io and download these both. So, we can then click on download for the Tiled Map Editor. No thanks, just take me to downloads. And you just wanna then download the version for your specific version of Windows pretty much. So once that finishes downloading, you will have a setup window pop up. We’ll just go through these things here and just set it up and yeah. So when it’s done, we’ll be back and we’ll be ready to create our tilemap.

Okay, so when that’s finished you should see that Tiled has now opened, and what we can do is we can choose to create a new map, a new tileset, or open a file. So for this one, we are just going to create a new map. We’ll keep all these settings the same, for now, since we’re just focusing on a tutorial right now, I’m just gonna accept the map width to about 30 by 30. You can, of course, set this to much more if you want, but we’ll just set it 30 by 30 for now. And the tileset we are going to use is going to be 32 by 32 pixels per tile. So that’s all good. We can click save as and we’ll just save this inside of a folder on our desktop for now.

And here we are in our map. Now, to move around in Tiled you can use the middle mouse button to drag. You can use scroll wheel to go up and down, and then Control and scroll wheel to zoom in and out. Oh, and scroll wheel to scroll horizontally.

So, with our map here, we want to start adding in some tiles. So what we’re gonna do is we’re gonna click on the bottom right here where it says new tileset, and we’re just gonna enter in a name for our tileset. We’ll just call this Tiles for now. So we can click on browse and find that asset. Here we are, I got it loaded up. Everything’s all good here. We can click save as now and here we go. We got our tilemap here. Everything’s set up. There are quite a few tiles in here for us to use.

So back in our actual tilemap here – not our tilemap but our actual map where we can start to create our tiles. What we want to do is, we want to divide this up into two separate layers. The first layer is going to be the background tiles, the tiles, of course, that we’re gonna be able to walk along. And the second tiles is going to be the collision tiles, and these are gonna be tiles that the player’s gonna be able to collide in. So this can be walls, mountains, tree, water, all the sort of things that you don’t want the player to be able to walk over.

So up here in our layers window, we’re gonna rename by double-clicking on the tile layer one. We’re just gonna call this background and then down here, we’ll click on this icon, open it up and click tile layer to create a new tile layer, and we’ll just call this one collision. Now, there’s also a rendering – rendering sorting as well so the collision tiles will render on top of the background tiles since that is now on top.

So yeah, we can now go in here, choose our tiles. Select the tile that you want. You can click to draw. You can also then go up here to the eraser to rub it out. Click on the stamp to go again. Select tile and then draw again. So yeah, it’s pretty intuitive up here. There are various other things as well. You click on here to draw a large box. So yeah, just use these tools. Create whatever sort of map you want. Make sure that if you do want the player to be able to collide with something that you do select the collision layer and then draw on that. But if you want something for the players to walk on top of, then draw that, of course, on the background layer.

So here we go. I’ve created my tilemap, and now what we can do is go back into Unity and, basically, import this. Now what we can do is download SuperTiled2Unity. The link for this will be in the lesson summary down below and what this is, is basically a tool for Unity that allows us to drag in a Tiled tilemap and then easily convert it to something that we can use inside of Unity.

So, with this here, we can just click on download again and what we want to do is just download the latest Unity package here. There’s one from two days ago, so we’ll download that and with this download, what we want to do now is actually drag this into our Unity project. So just drag that in like so. Wait for this to download. It’s just gonna be like when we imported Photon. We have all of this stuff here. We’ll keep all that. So, actually, we’ll just remove the examples folder here, since we don’t need that, and then we’ll just click on the import button.

So back here in Unity, what we want to do is create a new folder, and we’ll just call this one Tilemap and inside of that we want to drag in the three files that we’ll be using and that is going to be our background, our png file which has all the different tiles on it, the tileset as well, the .tmx, and the Tiled Map file which is our actual tilemap. So we just drag those three files in, wait for them to import, and once again, you should see that they each have their own little icons. The tileset has its icon and the tmx has its own icon.

So, first thing you want to do is click on our tiled.tmx, and we want to change the pixels per unit from 100 to 32, as that is how large each of our tiles are. We can just click apply then and after that we also want to do one more thing on here. We want to click tiles as object and then click apply. And what this will do is actually make it so that each tile is its own object that we can apply a collider to. So after that, you should see that the icon has changed. The tileset here, we also want to change the pixels per unit from 100 to 32. Click on apply. And after that it’s just converting all the tiles to the new pixels per unit and now what we can do is actually drag in our map.

So we can just drag it into the scene like so, and if we click on the scene view, you can see if you’re in 2D mode. Just click on this button to toggle 2D mode. You can see that we have our map. It’s all here. We have all our tiles. We can click on the individual tiles, move them around if we wish. Now, the anchor point for this map is in the top left corner. So what we do want to do is make sure that we have it in the center. Now my map is 30 by 30, so that means that 15 to 15 is gonna be the middle. So we’ll set X here to negative 15 and Y to 15 so that it is nice in the middle here and zero, zero is directly into the center of the map.

Okay, now inside of here we want to add our colliders. So if you remember, we have the background and collision layers, and so what we do want to do is only add colliders onto the collision layer. So, we can open up collision here, select all the tiles inside of collision, and then what we’re going to do is, in the inspector, add a box collider 2D component to that. So as you can see now, all of our collider tiles has its own box collider on it. So we won’t be able to walk on the water. We won’t be able to walk through trees or walls and it should be blocking us just fine.

So yeah, I’ll see you all then in the next lesson.

Interested in continuing? Check out the full RPG – Multiplayer Projects course, which is part of our Multiplayer Game Development Mini-Degree.

]]>
Creating a Multiplayer Battle Royale Map & Camera https://gamedevacademy.org/multiplayer-battle-royale-tutorial/ Fri, 09 Aug 2019 15:00:32 +0000 https://gamedevacademy.org/?p=10207 Read more]]>

You can access the full course here: Battle Royale – Multiplayer Projects

Part 1

Folder Structure

Let’s start by setting up out folder structure and 2 scenes.

  • Materials
  • Models
  • Photon
  • Prefabs
  • Resources
  • Scenes
    • Game scene
    • Menu scene
  • Scripts
  • Textures

Menu Scene

In our menu scene, let’s setup the camera for when we do the menu UI in a later lesson.

  • Set the Clear Flags to Solid Color
  • Set the Background to a green-blue color
  • Set the Projection to Orthographic

Unity Inspector for main camera

Game Scene

In our game scene, let’s setup our map. First, we’ll drag in the Terrain model.

  • Create an empty game object called _Map and drag the terrain in as a child of that
  • Set the Position to 0
  • Set the Scale to 10
  • Create a new material called Terrain and apply it to the terrain model
  • Add a Mesh Collider component to the terrain

Unity scene with green terrain mesh added

You might notice that the shadows are quite dark. To fix this we can go to the Lighting screen (Window > Rendering > Lighting) and click on the Generate Lighting button at the bottom.

Unity Inspector with Generate Lighting selected

Building our Map

Now we’re going to create the various structures and put them around our map. Let’s start by dragging in the Building model. Like with the terrain, we can create a new material and apply it to the model.

Right now we’d be able to walk through the walls. So what we need to do, is add a Mesh Collider component. This will make a custom collider to match the dimensions of the mesh.

Unity Mesh Collider component

Finally, we can save it in our Prefabs folder to both use later, and make sure all changes are applied to all instances.

Unity building prefab in assets

Do the same for the Barrier and Platform models.

Unity scene with barrier and platform added

Finally, we can go around and populate the map with our structures.

Unity scene with battle royale map

In the next lesson, we’ll start to create our network manager.

Part 2

CameraController Script

Create a new C# script called CameraController and attach it to the main camera. In this lesson, we’ll just be setting up the spectator camera functionality. When we create our player controller, we’ll do the rest. First up is our variables.

[Header("Look Sensitivity")]
public float sensX; 
public float sensY;

[Header("Clamping")]
public float minY;
public float maxY;

[Header("Spectator")]
public float spectatorMoveSpeed;

private float rotX;
private float rotY;

private bool isSpectator;

The first thing we want to do is lock and hide the mouse cursor in the Start function.

void Start ()
{
    // lock the cursor to the middle of the screen
    Cursor.lockState = CursorLockMode.Locked;
}

For actually checking the input and applying it to our rotation, we’ll be doing that inside of the LateUpdate function. The reason for this, is that doing it in the Update function, can cause jittering.

void LateUpdate ()
{

}

First up, let’s get our mouse inputs.

// get the mouse movement inputs
rotX += Input.GetAxis("Mouse X") * sensX;
rotY += Input.GetAxis("Mouse Y") * sensY;

Then we can clamp the vertical rotation.

// clamp the vertical rotation
rotY = Mathf.Clamp(rotY, minY, maxY);

For the spectator camera, we’re going to be able to look around as well as moving with the keyboard.

// are we spectating?
if(isSpectator)
{
    // rotate the cam vertically
    transform.rotation = Quaternion.Euler(-rotY, rotX, 0);

    // movement
    float x = Input.GetAxis("Horizontal");
    float z = Input.GetAxis("Vertical");
    float y = 0;

    if(Input.GetKey(KeyCode.E))
        y = 1;
    else if(Input.GetKey(KeyCode.Q))
        y = -1;

    Vector3 dir = transform.right * x + transform.up * y + transform.forward * z;
    transform.position += dir * spectatorMoveSpeed * Time.deltaTime;
}
else
{

}

Back in the editor, we can fill in the values.

  • SensX = 10
  • SensY = 10
  • MinY = -90
  • MaxY = 90
  • SpectatorMove peed = 10

 

Transcript 1

Hey everybody and welcome to the course. My name’s Daniel Buckley and I’ll be instructor. Let’s have a look at what we’ll be making.

We are going to be creating a multiplayer, 3D, battle royale game. Here’s an example of two players who are playing the game. The player on the right, you can see, can kill the player on the left, and once he does that, he is the last player alive and wins the game. This can feature as many players as you want. We are just going to be testing it out with around two or three, but as you can see, we have a level here and we also have a force field in the background that closes in.

For this project, we will be using Photon Unity Networking. This is a free networking framework that is very useful and very popular within Unity. It’ll allow us to connect servers, create rooms, have lobby browsers, and send each other messages to create a fully working multiplayer game.

So one of the first things we’ll create is the player controller. This is what you will control. You’ll be able to move, jump, shoot, heal when you pick up a health pack, and add ammo when you pick up an ammo pack. When a player gets hit by a bullet, they take on damage; and when their health reaches zero, they will die and the camera will actually become a spectator camera so you’ll then be able to fly around the map and look at the remaining players while they play the game.

We’ll also have pickups, health and ammo packs, that the player can find around the map, and just like any battle royale game, we have a force field that will encapsulate the players and force them into smaller and smaller areas on the map. This will damage the player every second or so while they’re outside the force field, and it will shrink every so meters every so and so seconds. This is a very customizable force field that we’ll be creating.

One of the things we’ll also create is a lobby and menu system. Players can join a game and wait in a lobby before starting. On the left is our lobby browser. When a player creates a game, the players will be able to find it in the lobby browser. As you can see, it has the room name, as well as how many players are currently in it, and then on the right we have the actual lobby. This will display all the list of players who are in the room, as well as the name of the room, and it’ll allow the host to begin the game whenever they want.

To do this, we’ll be using Unity’s UI system. On the left is what the game UI will look like. We’ll use sliders for the health bar, text for all the stats and even an image for crosshair. On the right we have the same thing. We have, this time, also a scroll bar. We’ll be learning how to use the scroll racks and setting all that up to create a dynamic server browser as well so that you can update constantly when you click the refresh button.

So, ZENVA is an online learning academy with over 400,000 students. We feature a wide range of courses for people who are just starting out or for people who just want to learn something new. Our courses are also very versatile. You can view them wherever you are and whenever you want. There’s also lesson summaries so you can choose to follow along and watch the videos or even read the courses and we’ve included project files. You can create the project however you want. Now with all that said, let’s get started on our project.

Transcript 2

Welcome back, everyone! In this lesson, we’re gonna be setting up our project, and first of all, our project file structure. Then we’re gonna move on and set up each of our scenes.

So, to begin, let’s create our folders. We’ve already got our Photon and Scenes folder right here. So let’s create another folder, and this one is gonna be called Prefabs. Now, this is where we’re gonna be storing all of our different Prefabs that we’re gonna be using. Let’s also make a folder called Materials, to store our materials in, and then another folder for our models.

This project also comes with some included files and some of those are models that we’re gonna be using. So, these models are the AmmoBox, Barrier, Building, Force Field, Health Pack, Platform and Terrain. So, I’m just gonna drag those in right here.

Apart from that, we also then want to create another folder here. This folder is gonna be called our Scripts and this is where we’re gonna be storing all of our different scripts we’re gonna be creating and then another folder for the resources. And in the Resource folder, I’ll get into more detail about this later, but, this is where we need to put Prefabs that we want to instantiate over the network with Photon. I’ll go into this in more detail later on, when we actually start instantiating those, but for now, let’s create our next folder, and this folder is going to be called Textures.

Now, the only texture we’re really gonna be having is going to be our CrossHair, which is another included asset in the project files, so you can just drag that in. And by default, let’s actually just set this up right now, let’s click on this crosshair right here, and we have to change the texture type from default to Sprite, 2D and UI. And just click on apply, like so. And that’s all we have to do. And that’s it for the folders.

Now, let’s go into our scenes folder, and we want to create two new scenes. The first scene we want to create is going to be our menu scene, which is going to be where we can create lobbies, join rooms, and then start the game. And then we want our next scene to be the actual game. And this is where all the action is going to be taking place.

And let’s actually open up the menu scene right now and inside of here, we can go into the game view, have a look. Let’s actually set up the camera as well right now. So let’s click on the main camera, and we want to change its projection from Perspective to Orthographic. The reason for that is because since we’re working with UI and 2D aspects in this scene, we don’t really need depth, because we’re not trying capture distance of 3D objects. So we can set it to Orthographic to make it much easier, and we’ll actually change the background, because we don’t really want this skybox background for a menu. So what we can do is click on Clear Flags up here and change that from SkyBox to Solid Color. And this color can then be changed here, and let’s change this to a sort-of greeny-blue color. Something like this.

All right, and with that done, let’s now save that and go into a game scene where we are gonna create our level. So, first thing, let’s go our models folder, and we want to drag in the terrain model right here into the scene. Now, it doesn’t have texture on it just yet, but before we do that, let’s actually set-up the hierarchy here a bit.

Let’s right-click and go Create Empty and we’re gonna call this one, let’s zero this out, we’re gonna call this one _Map. Now, this is just gonna be an empty game object that’s gonna be holding all of our, all of the objects that are related to the map. All of the structures and stuff like that. Just so it’s a lot neater here in the hierarchy and we can look through it and understand what object is for what thing.

So, let’s drag our terrain into the map object right here and let’s actually make a texture for this terrain. So, let’s go to our materials folder that we just created we’ll right-click here, go Create, Material and let’s call this Terrain. To apply a material, we can simply drag this on like so and let’s change this material over here, let’s set the smoothness all the way down and let’s change the albedo color to a green. So, we’ll go green here. Yeah, something like that.

You may notice though that the shadows look quite dark and not really that good. This is just how it is by default, but what we can do to easily fix this is go over to the Lighting Panel. If you don’t have the Lighting Panel, you can go up to Window here, go Rendering, and then Lighting Settings. And once we’re on here, all we need to do is just click on the Generate Lighting button down here at the bottom right. Just click that, it should take barely any time and there we go, it’s done. We have our shadows and everything and it looks so good now. Since we’re using real-time lighting, we don’t really have to do that again, unless you want optimize it. But, for us, we’re fine just like this.

So, with our terrain, we can now, and it might look a bit too bright, that green. So, let’s change this to something a bit more green like that, I reckon. That green looks good. So we’ll keep it like that. Now, the thing with our terrain right now is that it looks pretty good, it looks pretty much the size, but the problem is, we want to be using Unity units. We want to be scaling everything within the units inside of Unity. And that just makes it a lot easier for the physics to work as we want and just makes things, everything to scale.

So, what we can do now is just right-click here, just do for reference, go to 3D object, Cube and this cube here, if we zero this out, is one by one meter. Now, if we compare that to the rest of the terrain, it makes the terrain look quite small in comparison to that one meter cube. So, let’s get our terrain here, and let’s scale it up a bit. Let’s set the scale here to maybe 10 by 10 by 10. With that done, we can actually delete that cube, and let’s start on actually adding in our buildings and all about that.

So, let’s go to our models folder again, and we actually drag in the building asset right here. Just like that. Let’s create a texture for it, by going back to our materials folder. We’ll create a new material and we’ll call this one Building. Let’s apply it to the building here, and we’ll set the smoothness back down to zero again. And for the albedo, let’s set this to maybe a sort of dark brown sort of color like that. Yeah, something like that, there we go.

At the moment though, if we click on a building, we’ll see that we can actually, we actually don’t have a collider on it. So, people can walk through the walls, they can shoot through the walls, but we don’t want that. So, we’re gonna be adding a component here, and the component we want to add is going to be a mesh collider. And what this does is this makes it so that basically the mesh is a collider. It’s not necessarily a box collider or sphere collider; it just has it so you can’t walk into the actual object itself. So, the collider covers the entire object. There we go.

For this building, let’s actually go to our Assets window, into our Prefabs and let’s actually save this as a Prefab, so we can easily use it later on. We’ll just keep it, call it Building, and let’s drag it into here. We’ll go original Prefab and there we go, with our building asset. Our building Prefab saved, so let’s actually drag this into our map object, as that’s where it belongs.

Let’s add in our next environment model, which is gonna be the barrier. And this is just gonna be a sort-of shield of protection that the players can hide behind. Let’s again add a mesh collider to cover that. And let’s actually change this default white material to something else. So, we’ll create a new material in our materials folder and we’ll call this one Barrier. We’ll apply that, set the smoothness down to zero, and for the albedo, let’s make this say, sort of dark, dark gray like that. Yeah, something like that. Okay, that barrier is done, so let’s drag that into our Prefabs folder as well. We’ll make a Prefab of that, original Prefab.

And, the last thing we need to make is going to be our platform. This is just gonna be another structure that the players can climb up on top, look out from the top of, and shoot other players from. So, let’s actually re-use some of our materials, because what we can do is, for this platform here, we can set this as the building material there, and for the centerpiece, we can just do that as the barrier. So, there we go, we can reuse material like that, we can create new materials, if you want, for this, but I reckon we’ll just keep it with this sort of theme like that. It just looks pretty nice.

So, yeah, with these three things here, let’s actually first of all, go to Prefabs and save this platform as a Prefab, like so. And actually, we need to add in our colliders for this as well, so inside of here, we can select the cube and the other cube here, for both the different models, go Add Component, Mesh Collider. Click on the platform here, we can drag that back into the Prefabs folder, save it as a Prefab and there we go.

Now, what I’m gonna do is, I’m just gonna go around, I’m going to design the map. You can choose where you want to place them how many different objects you want, but just customize your map. Put things where you want and yeah, so I’ll be back once my map is finished.

So, there we go. I’ve got my map complete. I just put the houses, I’ve put the buildings around the different areas here up on this little hill here in different little areas and mixed around that with the towers, as well as the barriers. Something we also have to do, that I just remembered, is actually add a collider to our terrain, because otherwise, we’ll just fall right through the floor. So selecting the terrain, let’s just add a component, and add a mesh component, just, add a mesh collider, just like all the other ones. And that’s all we needed to do.

In the next lesson, we’re gonna be starting on our network manager, which is gonna be actually connecting us to the Photon Servers and allowing us to create rooms, join rooms, and all the rest. So, I’ll see you all then.

Transcript 3

All right, welcome back everyone. In this lesson, we’re gonna be starting to create our camera controller script.

At the moment, I’m in the game scene right now, and let’s actually create a new script here in our scripts folder. And we’re gonna be calling this one CameraController. Now with our camera controller script, let’s actually attach this to our camera by just dragging that on like so and opening it up in Visual Studio.

Now there are gonna be two different modes for this camera. There’s gonna be the first one where it’s actually attached to the player, and they’ll be able to look around, they’ll be able to look horizontally and look vertically. And then when the player dies the player will go into spectator mode, which will allow them to fly around the map using WASD or the arrow keys, and they will still be able to look around. So it’ll allow them to view the battle even after death.

So let’s remove the Start and Update functions here, as we won’t be needing them, and begin with our variables. Now we’ll be needing a few variables to keep track of the different sensitivities and positions and rotations. So I’m gonna separate these by headers, which is an attribute like so. And this just has a bold text in the inspector, so we can easily differentiate these.

And the first one we’re gonna do is going to be Look Sensitivity. And for this we’re gonna have a public float senseX for our X-axis sensitivity. And another one for a float for our senseY for our Y-axis sensitivity when we move the mouse. Then we also want to clamp our rotation, so got clamping and this is going to be our public float, minY, so what’s the lowest Y rotation we can look at. And then for the max, which is going to be maxY and what is the most vertical we can look – so how high up can we look before it clamps.

And then after that we then want to know for spectator, so we’ll go Header Spectator but then want to know how fast the spectator can move. So spectator or just go spectatormovespeed here. And after that we’re gonna go into our private variables. And first of all we then want to know our private float rotX, so what’s our current X rotation and the same for the Y, so what’s our current Y rotation. And that’s it for all the variables.

Now what we want to do first of all is – in many games you may notice that once you hop in it you can no longer see the mouse and the mouse actually doesn’t go off the screen. And that is because the mouse cursor is locked, and to do that inside of UNC we will do this in the Start function here. We will lock the cursor, so we can actually access the curse by going cursor and then lockstate and this is equal to CursorLockMode.Locked. So the cursor will be stuck in the middle of the screen, and it will be invisible. So it’ll feel just like all those other FPS’es.

Now let’s get on to working on in the main part of this script which is gonna be actually rotating and moving the camera. And to do this we’re gonna not do it in the update function, but we’re gonna be doing it in the Late Update function. Now what the Late Update function is, is this is basically just like the Update function, but this runs at the end of the frame. So this runs after everything in the other update functions has already run.

And the reason for doing this, is because when the camera is attached to the player and we’re doing the rotations and all that, there can be some interference with how the player rotates compared to how the camera then rotates. So it can have some sort of jittering if we have this in the Update function. But having it in a Late Update function solves those issues.

So first thing we’re gonna do is we wanna get the mouse movement inputs. And to do that we can go rotX, so we’re gonna add to our X rotation, that is going to be done by plus equals input.GetAxis. And the axis we want to get is going to be Mouse X like so. And then, of course, we want to multiply that by our X sensitivity. And again for the Y we can go rotY plus equals input.GetAxis mouse Y and multiply that by our senseY just like that.

Okay, now what you want to do is you want to clamp the vertical rotation so that we can’t look all the way up, and then wrap back around as that can cause some issues with the rotation and cause the controls to actually flip. So we’re gonna be clamping the rotation so that it doesn’t do that, and we can only look so far vertically and so far down. So to do that we can go to rotY as Y is gonna be the up-and-down rotation and that is gonna be equal to the mathf.clamp. And we wanna send in the value where we want to clamp – that is rotY. The min, which is going to be minY, and Max, which is going to be the maxY, like so. Great,

With that done we can then check are we spectating or are we not spectating – or so are we alive or are we dead. So are we spectating? And for that we can just go if isSpectating, if isSpectator then we’ll do whatever’s in here. Otherwise, if we attach the player will do this, and the reason for this is because as well as having the movement when we’re a spectator, when we attach the player to our X rotate, we don’t actually rotate the camera horizontally. So we won’t be looking left and right, instead we’ll be rotating the player left and right. And the reason for that is so that we can easily have the player point in the forward direction that we’re looking (so we don’t have to do some other calculations later on in the player controller).

So let’s work here in the isSpectator first, as that’s what we’ll be setting up this lesson. So first of all we want to rotate the camera vertically, and to do that we’ll just go transform.rotation equals Quaternion.Euler. And we just wanna pass in our negative rotY and our rotX. We’re doing negative rotY because it is flips, if you do wish to have inverted Y controls, then you can just have that as rotY. Okay, and then for the Z rotation, we just want zero as we don’t want the camera tilting left and right.

And now for the movement, we can go here, and we can just go for our X input. We can go input.GetAxis horizontal, so this is going to be our horizontal input, and then we can go for our forward input. So when we’re in forward and backwards they can go equal to input.GetAxis vertical, so the up and down keys compared to the horizontal which is the left and right keys. And for the Y this can be equal to zero for now as we’re gonna be changing it down here.

Now for the Y we’re also gonna make it so that the player can move up and down and that’s gonna be done with the E and Q keys. So if input.GetKey, KeyCode.E then Y is gonna be equal to one else if input.GetKey, KeyCode.Q then we’re gonna be setting y to equal to negative one so they’ll move down. N

ow to apply that, we need to do a calculation right now to make it so that when we move, we’re moving in the direction that we’re looking. Because if we just applied these X, Z and Y directions to our transform at the moment, that would move us based on the global positions and rotations. So if we’re looking to the left we might instead move forward if we try and move left for example. So what we’re trying to do is we wanna make it so that no matter where we’re looking we will move forward, left, right and backwards relative to our rotation.

And for that we’ll create a Vector3, call that dir for direction and that will be equal to transform.right, so our right transform direction. So the direction that is to our right, multiply that by X plus transform.up, multiply by Y plus transform.forward, multiply it by Z. And with that, we can then apply that to our local position we’re going. Transform.position plus equals dir at the direction we want to travel times SpectatorMoveSpeed times Time.deltaTime (so it is independent of framerate), and we move at the exact same time no matter what framerate we have.

And that’s that, let’s actually hop now back into the editor here and test it out. Let’s actually go back in here and just set isSpectator to true for now manually, so that we can test it out. And for our X sensitivity, I will zoom in here. For our X sensitivity, we can set this to – and I’ll say 10 for now, Y is 10, min Y will set this to negative 90, Max Y 90. Spectator Move Speed will go 10. Okay and let’s press play and see if this works. See if we can look around. As you can see I can look around with the mouse, and with the arrow keys I can move like so. I can press E to go up, Q to go down.

In the next lesson, we’re gonna be starting on our player controller. Connecting up the rest of the camera to the player and finishing off the camera script when it’s actually attached to the player so that we rotate not only the camera, but the player as well to face the direction. Also when you’re in this mode you can’t really press the play button. So what you can do is you can either go press Escape to get the mouse like so and click it or you can just go control + P to toggle the plane like so. So yeah I’ll see you all in the next lesson.

Interested in continuing? Check out the full Battle Royale – Multiplayer Projects course, which is part of our Multiplayer Game Development Mini-Degree.

]]>
An Introduction to Photon for Multiplayer Games https://gamedevacademy.org/unity-photon-tutorial/ Fri, 26 Jul 2019 15:00:25 +0000 https://gamedevacademy.org/?p=10194 Read more]]>

You can access the full course here: Intro to Multiplayer Game Development

Part 1

What’s Photon?

Photon is a networking framework for Unity. It’s very similar in structure to UNet (now deprecated).

How Does Multiplayer Work?

Here’s how multiplayer in Photon and many other games works.

Visual image of computers connected to server

Players connect to a server and send / receive messages. These can be updates to other players positions, when a player shoots, when you get hit, etc. If there’s things you want other players on the server to know that is not being done directly on their computer, it will be sent through the network.

For example, if player 1 shoots their gun, that message will be sent to the server and then received by player 2 on their computer. They will then show player 1 shooting their gun and spawning a bullet.

By default in Photon, messages can be sent up to 20 times a second.

Master Server

A master server is a server on Photon for each game, or even unique versions of a game. This is where all the players and rooms for that game are located. Players can view all the existing rooms, join them or create a new one. You can only see rooms from the master server you’re in. You cannot join a room of another game.

By default, Photon can allow up to 20 players at once connected to the server. This can be upgraded on their site. They also feature servers all around the world.

Visual image of Rooms connected to Master server

Rooms

Think of a room like a match or lobby. This is where a group of players can send messages to each other. Sync values, positions, rotations, animations, etc.

Players

Players (aka clients) are the people that populate rooms. Each room has a master client (host). This is by default the player who creates the room and is useful for checking and running server side things.

Visual image of clients connected to room

Part 2

Setting up Photon

Before we can use Photon, we need to get an App Id. To do this, go to www.photonengine.com and click on the Sign In button. Either sign in or create a new account.

Photon website home page

Once you sign in, you’ll be taken to the applications page. Here, we want to click on the CREATE A NEW APP button.

User photon cloud applications page

Here, we can fill out the info for our new application.

  • Set Photon Type to Photon PUN
  • Enter a name for your app

Then click on the CREATE button.

New application creation page for Photon

This will take you back to the applications page. Here, you want to find your app and copy the App ID. This is how Photon will know what your game/app is and to keep track of analytics.

Photon App with App ID highlighted

Importing Photon into Unity

In Unity, create a new project and open up the Asset Store window (Window > Asset Store). Search for “photon 2” and download the PUN 2 – FREE asset.

PUN 2 asset in Unity Asset Store

When the import package window pops up, we’re going to disable some parts of the asset since we don’t need them.

  • Photon > PhotonChat
  • Photon > PhotonRealtime > Demos
  • Photon > PhotonUnityNetwork > Demos

Click Import, then once that’s done the PUN Wizard window should open. Here, we just want to paste in our app id and click Setup Project.

PUN Wizard window in Unity

Now Photon’s installed and ready to go!

 

Transcript 1

Hey, everyone, my name’s Daniel Buckley, and I will be instructor for this course. So this is what we’re going to be making. We are going to be making a 3D multiplayer game in Unity using Photon. Photon is a networking tool for Unity, and it’s one of the most popular ones currently in the world for the platform.

So the aim of our game is to hold the hat for a certain amount of time. This is going to be a multiplayer game where you can have as many players as you want really, but the aim of the game is to hold on to this hat, or any various object, for a certain amount of time. Once you hold on for that amount of time, you win the game. As you can see here, the players can also steal the hat from each other by running into each other, and this is just going to be a game that we can use to demonstrate many of the different features of Photon and networking inside of Unity.

We’re going to be creating a menu and lobby system which will allow players to join games and lobby up before jumping into the actual game. As you can see here, we have a lobby and there’s three players in it, and as the host, you will be able to start the game. We’ll also be working on a player controller. This player controller will be able to move, jump, and steal the hat from other players. When they hold on to the hat, their timer will increase, and if that timer reaches the maximum amount of time needed, then they will win the game.

All this stuff will also be done through networking, so we’ll be syncing the movement, the jumping, the stealing of the hat, through the network so that it appears on all other player screens at the same time. For all of this, we’ll be using Unity’s UI system, canvases, text, buttons, input fields, sliders, and more. These will be used on the menu to enter in the player name, the room name that you wanna join, as well as the buttons. In the game view here we have the sliders and the text to display the players and their current time, as well as who wins the game.

This is what our game loop is gonna look like. We’re gonna start on the menu, and then a player can either join or create a game, and that will place them inside the lobby. Once in the lobby, the host can start the game and that will load up the game scene, where they’ll begin to play the game. When a player who’s holding the hat reaches the winning time, that player wins the game, and all the players then go back to the menu.

ZENVA is an online learning academy with over 400,000 students. We feature a wide range of courses for people who are just starting out, or for people who just want to learn something new. The courses are also very versatile, allowing you to watch them whenever you want and however you want. There are included course project files that you can follow along to see the project and work along with it, and there’s also lesson summaries, so you can choose to read the course as well. With that all said, let’s get started on our project.

Transcript 2

Hey everyone. In this lesson, we’re gonna be talking about multiplayer in Unity and Photon, and actually work in all the different things that you really need before we actually get started.

So the first thing is what sort of multiplayer is there in Unity? Well, Unity used to have their own multiplayer network. If you’re watching this course sometime around early 2019, then you have UNet which is Unity’s old Unity Networking framework (it is now deprecated). So we won’t be able to use that. Instead, we’re gonna be using Photon. And Photon is the most popular Unity multiplayer framework. There are many popular games that use it, and it’s easy to use. If you’ve ever used UNet before, it’s basically the exact same thing, but with added features.

Alright. So, how does multiplayer work? Or what it is is we have multiple players connected together, and what they do is at its core, a multiplayer is basically just sending messages between computers. So, let’s just say player one here moves forward one unit, then that command or that actual new position of the player will be sent from the player- from the player over through the server to player two. So, on player two’s screen, player one is not one unit or at their new position.

And so, that’s how it works. You’ll be sending various amounts and messages every second. By default, I believe that Photon sends about 20 messages per second. You can, of course, tweak that, but it’s set at 20 to be nice, so it doesn’t have too much lag or too much problems with that. So yeah, that is at its core, is sending messages between computers.

Let’s just say you wanna do an attack. You cast the attack on your computer, and then you send that message over to player two’s computer, so if there are any visuals that go with that attack, those visuals can be displayed on their computer. And that is how you sync between computers, sync between states, positions, rotations, everything that you want to appear on other people’s computers, that is how you do it, through messages. And we’ll be going to some more detail on how to actually do this in code and in script, and also with Unity’s components, what stuff you need to set up, and all of that stuff in later lessons.

So the first concept we need to go over is a master server. What is a master server? Well, in Photon and even in Unity networking, a master server is basically the connection of rooms. I’ll go over rooms in a second. Players can connect to rooms, and there you can see a list of all the rooms. It’s basically like a sort of hub for your game. And each game has their own specific master sever, and even different versions of your game. You can specify it to have different master servers. So, if you’re on version one of your game, you can’t play with people who are on version two, for example. And of course, if you have your game, you can’t play with people who are in other games. You can only play with people on your game in your specific version of that game.

And the good thing about Photon is they have their own dedicated hosted servers all around the world. As you can see to the right, there are many locations around the world where you can basically connect your master server and your game to. In Photon, you can also do it so that for players it connects to the master server with the lowest ping. So you can try and always have the lowest ping possible, or you can just hard code it, so that you connect to a specific master server. Players on different master servers cannot play with each other. So you do need to keep that in mind when making your game.

And of course, with Photon, it is a service that you can choose to pay more to increase the capacity of the server. By default, your game can have up to 20 players at once with the free version of Photon, but you can of course pay for more, and yeah. Of course, you can also host your own server if you wish. That will, of course, require you to have your own server hardware setup and have all of the networking capabilities available. So, if you’re just starting out with networking, I recommend just keeping with the free Photon version as you can test it out. You test it out with your friends, with other people, with testers, and just to see if that is what you want. And if you do, you can wish to pay more further on later on in the future.

So this is what sort of the framework looks like. You have the master server and all the different rooms that players can create connect to that. And within those rooms, you have your own players. So these are very secluded areas away from each other. If one player and one room shoots their gun, then a player in another room won’t see that on their screen. Pretty much, if you’re in a room and all the messages you sent within that room only goes to the players in that room.

So let’s go over more about what a room is. Think of a room as a match or a lobby. These are groups of players who can send messages to each other and by sending messages to teach other, syncing values, positions, rotations, animations, et cetera. So yeah, think of your favorite game where you have your own lobby- you’re in match of 10, 20 players. It’s a self-contained version of the game where you are only communicating with each other and not other players in other matches on different apps, for example.

And in Photon and many multiplayer networks, players are also known as clients. The client is a computer that is connected to the network, and each room has a master client. You might know what a master client is by its other name- which is host. In Photon, a host by default is the player who created the room. And what it means to be a host is you can allow the host to do specific things. In our game, for example, when waiting in the lobby, only the host will be able to stop the game. And using the host for many other things is also a good idea.

If you have a first-person shooter for example or a game where you want to collect pickups, you won’t want players to detect picking up pickups on their own, on their own client. Because what that could do is if two players run into the same pickup at the same time, on their computer they will see that they’re the only one picking it up at that frame, whereas for the other person, that’ll be the same thing.

So what you wanna do is put these sort of processes through the host, so the host will check it. So when the player runs into a pickup, you check with the host. Am I in the pickup? If so, the player picks it up. And if not, you don’t. So there are only one ever person can pick up the pickup at a time. There are many different things, but we’ll go over these later on. But for now, this is just what a host is.

All right. So in the next lesson, we’ll be going over actually setting up our Photon app, connecting Photon and downloading the Photon assets inside of Unity to be able to use it. Alright. So see you all then.

Transcript 3

Hey everyone. In this lesson, we’re gonna be setting up our Photon app and importing the Photon assets we need inside of Unity. So the first thing that we need to do is go to photonengine.com, which will take us to Photon’s main website. And then what we wanna do is sign in or sign up. It’s pretty easy to make an account and you can easily register here, but I’ve already got one so I’m just gonna log in.

Alright, once you make your account or sign in you should be taken to the public cloud screen where you have your applications. If you are not on this screen you can just click on this icon up here and then click on your applications. I’ve already got two Photon applications here already set up, but what we need to do is create a new app. So we will click on the create a new app button right here. And this will take you over to the page where we can fill any information. The only things we need to add to here is the Photon type and the name.

For the Photon type we want to change this to Photon PUN. And Photon PUN is its Unity specific framework, which stands for Photon Unity Networking. And for the name, we can call it whatever we want. I am just going to call this, MyPhotonApp. You can also enter in a description and a website here if have- that you want to connect to your website. But I don’t so I am just going to click on the create button and this will take us back to our applications page where we now have our new Photon app ready to use pretty much.

As you can see we can have up to 20 concurrent players at once. This, of course, is upgradable and you can pay Photon to increase this number or you can choose to host your own server. But for now this is all we need. And the only actual piece of information we need here before opening it to Unity is the Photon App ID right here. So we can just click on that and copy that and pretty much get ready to use that inside of Unity, as we will need this. And that is about it for the Photon website.

So now let’s hop into Unity and begin pulling the Photon 2 assets. Alright, when you are inside of Unity the first thing you wanna do is go to the asset store window. If you don’t have this open you can go up here to Window, then Asset Store, and this will open up this window here. And the asset we want to download is going to be Photon 2. Then when you search for that, we just want to scroll down and find Photon 2 multiplayer free. So you can click on the import button or update if you’ve already downloaded before. And then we can just wait for that to download.

Now when we get to the import package window, we don’t actually need all of the assets that it comes with, so we are only going to choose the ones that we need. So, first of all, we can untick Photon chat, as we won’t be needing that. We need Photon libraries. And inside of Photon real-time, let’s not include the demos. And then inside of Photon Unity Networking, let’s also not include the demos, as we won’t be needing them. And everything else we need. So we can just click on import. And so pretty much the only things we’re not importing are the demos and Photon chat.

Once it’s done you should have a little window here called PUN Setup that pops up. And this will just ask for your App ID or email. We previously copied the App ID, so we will just paste that in like so and click on the setup project button. It will say we are done and we can click on close. And to the right here, we see it has the Photon service settings selected. We don’t need to go into this too much, but what we do now have is our Photon assets included in the project. So now in future lessons we can start to work on Photon.

And actually in the next lesson, we’re going to be setting up our project, setting up the folder structure, and creating an actual game level. So I will see you all then.

Interested in continuing? Check out the full Intro to Multiplayer Game Development course, which is part of our Multiplayer Game Development Mini-Degree.

]]>
How to Create a Multiplayer Bomberman Game in Unity – Part 3 https://gamedevacademy.org/how-to-create-a-multiplayer-bomberman-game-in-unity-part-3/ Mon, 07 Aug 2017 23:38:06 +0000 https://gamedevacademy.org/?p=5550 Read more]]> In the last tutorial we finished adding the single player features of our Bomberman game. Now, we are going to make it a multiplayer game, using Unity’s multiplayer support.

In order to follow this tutorial, you are expected to be familiar with the following concepts:

  • C# programming
  • Basic Unity concepts, such as importing assets, creating prefabs and adding components
  • Basic Tiled map creation, such as adding a tileset and creating tile layers

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Assets copyright

The assets used in this tutorial were created by Cem Kalyoncu/cemkalyoncu and Matt Hackett/richtaur and made available by “usr_share” through the creative commons license, wich allows commercial use under attribution. You can download them in http://opengameart.org/content/bomb-party-the-complete-set or by downloading the source code.

Source code files

You can download the tutorial source code files here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Network manager

In order to build a multiplayer game in Unity we need an object with the Network Manager component. So, create an empty object in the Title Scene and add the Network Manager component to it.

You can also add the Network Manager HUD component. This will show a simple HUD in the game that we can use to start multiplayer games. Later on we are going to create our own HUD buttons, but for now the Network Manager HUD will be enough.

By now, you can try playing the game and it should show the Network Manager HUD in the title screen. The next step is making this NetworkManager to create the multiple players in the game.

Creating the players

The NetworkManager component allows us to define what is the Player prefab in our game. This Player prefab will be created automatically by the manager every time a match starts. But before setting our Player prefab in the NetworkManager, we need to update some stuff in the Player prefab itself.

A prefab can be instantiated by a NetworkManager only if it has a NetworkIdentity component attached to it. So, let’s add one to our Player prefab. Also, the Player object should be controlled by the local players and not by the server, so we need to check the Local Player Authority box.

Now, let’s test our game and see if multiple instances of the Player are being created. But first, I’m going to explain how multiplayer works in Unity.

In Unity, there is no dedicated server for the matches. That’s because one of the players in a match acts as the server (besides being a client itself). The player that acts as both server and client is called a host in Unity. In order to play a multiplayer match, one of the players must start the match as the host, while the others join the match as clients. All game objects are replicated in all game instances (servers and clients), and all scripts are executed in all instances.

However, we can not open two instances of our game in the Unity editor. So, what we need to do is build an executable of our game and open it separately. You can do that by selecting File -> Build & Run in the editor. Then, we can start the other instance from the Unity editor.

Try opening two instances of the game. In one of them click on the LAN Host button of the Network Manager HUD. In the other one click on the LAN Client button. This should start the game in both instances, with two player objects.

However, there are a couple of problems we still need to address:

  • Both players are being created in the center of the screen. We want them to be created in predefined positions.
  • If we try moving the player in one client, both players are moved, and the movement is not propagated to the other clients.
  • Players should not collide among each others.

What we are going to do now is addressing all those issues.

Synchronizing player movement

Let’s start by making the players to spawn in predefined positions. We can do that by creating objects with the NetworkStartPosition in the Battle Scene. So, let’s create two of them (we want a battle with two players). Put them in the positions where you want the players to spawn.

Now, the Player Spawn Method attribute of the NetworkManager defines how it will choose the positions to spawn the players. There are two policies:

  1. Random: the starting position of each player will be randomly determined based on the available ones.
  2. Round-robin: given an order of the starting positions, the first player will be created in the first position. Then, the second player will be created in the second one and so on in a circular fashion.

In our case, we are going to use the Round-robin policy.

Now, you can try playing the game again, and the players should be created in the desired positions.

What we are going to do now is making sure each client can only move its own player, and that the movement is propagated through all clients.

We can make sure each client moves its own player by changing the PlayerMovement script. First of all, we are going to do something that will be necessary for every script that will use multiplayer features: we need to use the UnityEngine.Networking namespace and we need to make the script inherits NetworkBehaviour, instead of MonoBehaviour.

Then, we are going to change the script so that it looks like below. In the beginning of the FixedUpdate method (which controls the player movement), we are going to add an if clause that checks if this is the local player. This condition will be true for only one of the clients (the one that controls the player) and false for all the other ones. This way we can make sure that only one client will control each player.

Another thing we are going to add is implementing the OnStartLocalPlayer method. This method is similar to OnStart from the MonoBehaviour, but it will be called only for the local player. In this method we are going to set the color of the Player sprite to be red, so that each client can identify its own player.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class PlayerMovement : NetworkBehaviour {

	[SerializeField]
	private float speed;

	[SerializeField]
	private Animator animator;

	public override void OnStartLocalPlayer() {
		GetComponent<SpriteRenderer> ().color = Color.red;
	}

	void FixedUpdate () {
		if (this.isLocalPlayer) {
			float moveHorizontal = Input.GetAxis ("Horizontal");
			float moveVertical = Input.GetAxis ("Vertical");

			Vector2 currentVelocity = gameObject.GetComponent<Rigidbody2D> ().velocity;

			float newVelocityX = 0f;
			if (moveHorizontal < 0 && currentVelocity.x <= 0) {
				newVelocityX = -speed;
				animator.SetInteger ("DirectionX", -1);
			} else if (moveHorizontal > 0 && currentVelocity.x >= 0) {
				newVelocityX = speed;
				animator.SetInteger ("DirectionX", 1);
			} else {
				animator.SetInteger ("DirectionX", 0);
			}

			float newVelocityY = 0f;
			if (moveVertical < 0 && currentVelocity.y <= 0) {
				newVelocityY = -speed;
				animator.SetInteger ("DirectionY", -1);
			} else if (moveVertical > 0 && currentVelocity.y >= 0) {
				newVelocityY = speed;
				animator.SetInteger ("DirectionY", 1);
			} else {
				animator.SetInteger ("DirectionY", 0);
			}

			gameObject.GetComponent<Rigidbody2D> ().velocity = new Vector2 (newVelocityX, newVelocityY);
		}
	}
}

You can try playing the game now, and each client will be able only to move one player. However, the movement is still not being propagated to the other client. We can do that by adding two components to the Player prefab: NetworkTransform and NetworkAnimator. The first component will send the Player position all clients according to the Network Send Rate attribute. The second one will synchronize the animations among all clients (you only need to set the animator of the object). Now, if you try playing the game, the movement should be synchronized correctly.

Finally, what we are going to do is making players to not collide with each other. We can do that by setting a Layer to the Player prefab and changing the Physics settings to disable collisions among objects of this Layer. You can create a new Layer by clicking on Add Layer on the object inspector. You can edit the Physics settings by clicking on Edit -> Project Settings -> Physics 2D Settings.

With that we have finished addressing the player movement issues. Now we are going to synchronize the creation of other objects, such as bombs and explosions.

Synchronizing bombs

The first thing we need to do in order to create Bombs and Explosions is adding the NetworkIdentity and NetworkTransform components to their prefabs, as we did with the Player. However, after those objects are created, they do not move around the screen. So, we can set the Network Send Rate of both of them to 0, in order to reduce the network traffic.

Now, we need to change the BombDropping and BombExplosion scripts to work in a multiplayer scenario.

Let’s start by the BombDropping script. We want clients to drop bombs only from their own palyers, so we are going to check again if it is the local player before dropping the bomb.

Also, here we are going to make use of a new Unity multiplayer concept, called Command. A Command in Unity is a method that is always executed in the server. If it is called from a client, the client will send a message to the server asking it to execute the method. In order to turn a method into a command we must add a [Command] tag before the method, and the name of the method must start with Cmd.

The last thing we need to change here, is spawning the bomb in all clients after we instantiate it. We can do that using the NetworkServer.Spawn method. This method receives as parameter an object and creates a copy of this object in all clients. Notice that this method can only be called from the server (which is fine because we are calling it inside a Command). However, we still need to check if the NetworkServer is active before doing so. Finally, the BombDropping script should look like below.

public class BombDropping : NetworkBehaviour {

	[SerializeField]
	private GameObject bombPrefab;
	
	// Update is called once per frame
	void Update () {
		if (this.isLocalPlayer && Input.GetKeyDown ("space")) {
			CmdDropBomb ();
		}
	}

	[Command]
	void CmdDropBomb() {
		if (NetworkServer.active) {
			GameObject bomb = Instantiate (bombPrefab, this.gameObject.transform.position, Quaternion.identity) as GameObject;
			NetworkServer.Spawn (bomb);
		}
	}
}

Now, let’s update the BombExplosion script. Here, the only things we need to change is turning the methods into Commands and propagating the objects creation and destructions. So, turn the Explode and CreateExplosions methods into Commands (by adding the [Command] tag and changing their names). After instantiating each explosion object we need to call the NetworkServer.Spawn method, as we did with the bombs. Also, when destroying blocks (when an explosion hits a block), we need to call the NetworkServer.Destroy method, in order to propagate the object destruction among all clients.

public class BombExplosion : NetworkBehaviour {

	[SerializeField]
	private BoxCollider2D collider2D;

	[SerializeField]
	private GameObject explosionPrefab;

	[SerializeField]
	private int explosionRange;

	[SerializeField]
	private float explosionDuration;

	void OnTriggerExit2D(Collider2D other) {
		this.collider2D.isTrigger = false;
	}

	[Command]
	public void CmdExplode() {
		if (NetworkServer.active) {
			GameObject explosion = Instantiate (explosionPrefab, this.gameObject.transform.position, Quaternion.identity) as GameObject;
			NetworkServer.Spawn (explosion);
			Destroy(explosion, this.explosionDuration);
			CmdCreateExplosions (Vector2.left);
			CmdCreateExplosions (Vector2.right);
			CmdCreateExplosions (Vector2.up);
			CmdCreateExplosions (Vector2.down);
			NetworkServer.Destroy (this.gameObject);
		}
	}

	[Command]
	private void CmdCreateExplosions(Vector2 direction) {
		ContactFilter2D contactFilter = new ContactFilter2D ();

		Vector2 explosionDimensions = explosionPrefab.GetComponent<SpriteRenderer> ().bounds.size;
		Vector2 explosionPosition = (Vector2)this.gameObject.transform.position + (explosionDimensions.x * direction);
		for (int explosionIndex = 1; explosionIndex < explosionRange; explosionIndex++) {
			Collider2D[] colliders = new Collider2D[4];
			Physics2D.OverlapBox (explosionPosition, explosionDimensions, 0.0f, contactFilter, colliders);
			bool foundBlockOrWall = false;
			foreach (Collider2D collider in colliders) {
				if (collider) {
					foundBlockOrWall = collider.tag == "Wall" || collider.tag == "Block";
					if (collider.tag == "Block") {
						NetworkServer.Destroy(collider.gameObject);
					}
					if (foundBlockOrWall) {
						break;
					}
				}
			}
			if (foundBlockOrWall) {
				break;
			}
			GameObject explosion = Instantiate (explosionPrefab, explosionPosition, Quaternion.identity) as GameObject;
			NetworkServer.Spawn (explosion);
			Destroy(explosion, this.explosionDuration);
			explosionPosition += (explosionDimensions.x * direction);
		}
	}
}

Finally, since we turned the Explode method into a Command, we need to update the ExplosionDamage script accordingly.

public class ExplosionDamage : MonoBehaviour {

	void OnTriggerEnter2D(Collider2D collider) {
		if (collider.tag == "Character") {
			collider.gameObject.GetComponent<PlayerLife> ().LoseLife ();
		} else if (collider.tag == "Bomb") {
			collider.gameObject.GetComponent<BombExplosion> ().CmdExplode ();
		}
	}
}

The last thing we need to do is setting the Bomb and the Explosion prefabs as Spawnable Prefabs in the NetworkManager. We can do that by adding them to the Spawnable Prefabs list of the component.

By now, you can try playing the game and creating bombs. Bombs should be synchronized among all clients, as well as their explosions.

Controlling player life

Until now, the lives of both players are being incremented in both clients. We want each client to show only its lives. We can do that by changing the PlayerLife script as follows. We need to add an if clause in the beginning of the Start method to check if this is the local player.

Since the lifeImages List is local for each client, we need the LoseLife method to execute only for the local players as well. Also, when the number of lives reach 0, we are not going to show a game over screen anymore, we are simply going to respawn the player to its initial position. The respawn method will also rebuild the lifeImages List. Notice that, in order to respawn the player, we need to save its initial position and initial number of lives in the Start method.

public class PlayerLife : NetworkBehaviour {

	[SerializeField]
	private int numberOfLives = 3;

	[SerializeField]
	private float invulnerabilityDuration = 2;

	private bool isInvulnerable = false;

	[SerializeField]
	private GameObject playerLifeImage;

	private List<GameObject> lifeImages;

	private GameObject gameOverPanel;

	private Vector2 initialPosition;
	private int initialNumberOfLives;

	void Start() {	
		if (this.isLocalPlayer) {
			this.initialPosition = this.transform.position;
			this.initialNumberOfLives = this.numberOfLives;

			this.gameOverPanel = GameObject.Find ("GameOverPanel");
			this.gameOverPanel.SetActive (false);

			GameObject playerLivesGrid = GameObject.Find ("PlayerLivesGrid");

			this.lifeImages = new List<GameObject> ();
			for (int lifeIndex = 0; lifeIndex < this.numberOfLives; ++lifeIndex) {
				GameObject lifeImage = Instantiate (playerLifeImage, playerLivesGrid.transform) as GameObject;
				this.lifeImages.Add (lifeImage);
			}
		}
	}

	public void LoseLife() {
		if (!this.isInvulnerable && this.isLocalPlayer) {
			this.numberOfLives--;
			GameObject lifeImage = this.lifeImages [this.lifeImages.Count - 1];
			Destroy (lifeImage);
			this.lifeImages.RemoveAt (this.lifeImages.Count - 1);
			if (this.numberOfLives == 0) {
				Respawn ();
			}
			this.isInvulnerable = true;
			Invoke ("BecomeVulnerable", this.invulnerabilityDuration); 
		}
	}

	private void BecomeVulnerable() {
		this.isInvulnerable = false;
	}

	void Respawn() {
		this.numberOfLives = this.initialNumberOfLives;

		GameObject playerLivesGrid = GameObject.Find ("PlayerLivesGrid");

		this.lifeImages = new List<GameObject> ();
		for (int lifeIndex = 0; lifeIndex < this.numberOfLives; ++lifeIndex) {
			GameObject lifeImage = Instantiate (playerLifeImage, playerLivesGrid.transform) as GameObject;
			this.lifeImages.Add (lifeImage);
		}

		this.transform.position = this.initialPosition;
	}
		
}

If you try playing now, each Client should show only the number of lives of its local player. As a challenge, you can try showing a message with the winner player when a player dies.

Creating matches

Until now we are using the Network Manager HUD to star the host and the match. What we are going to do now is removing this HUD and creating our own buttons to create and join matches.

First, remove the NetworkManagerHUD Component from the NetworkManager. Also, remove the StartGameText, since we are going to replace it by the buttons.

Now, create a new button (UI -> Button) called CreateMatchButton as a child of the TitleCanvas.

Now, we are going to create a new script called MultiplayerMatch and add it to the NetworkManager object. This script will be used to create and join matches, which we are going to do now.

First, let’s create the methods to create a match. The MultiplayerMatch script will have as an attribute the NetworkManager, in order to access its method. Then, in the Start we are going to call the StartMatchMaker method from the NetworkManager. This method will enable the match maker methods, used to create and join matches.

Then, we are going to add a CreateMatch method which will be called by the CreateMatchButton when it is clicked. This method will call the CreateMatch method from the match maker. The parameters are: the match name, the maximum number of players per match, a boolean that makes the match to be listed, and other parameters such as password an minimum elo, that we are not going to use. The last parameter is the callback, which will be called once the match has been created. In our case we are going to call a OnCreateMatch method.

The OnCreateMatch method will simply set the client as the host and load the Battle Scene. We still need to start the game as a Host, but we are going to do that after creating the button to join matches.

public class MultiplayerMatch : MonoBehaviour {

	[SerializeField]
	private NetworkManager networkManager;

	public bool isHost = false;

	// Use this for initialization
	void Start () {
		networkManager.StartMatchMaker ();
	}

	public void CreateMatch() {
		networkManager.matchMaker.CreateMatch ("match", 2, true, string.Empty, string.Empty, string.Empty, 0, 0, OnMatchCreate); 
	}

	void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo) {
		this.isHost = true;
		SceneManager.LoadScene ("Battle");
	}

}

Finally, set the CreateMatch method as the callback of the CreateMatchButton.

Joining matches

The first thing we need to do to allow players to join matches is creating a button for that. So, similarly to what we did for creating matches, create a button called JoinMatchButton.

Now, let’s create the necessary methods in the MultiplayerMatch script. First, create a JoinMatch function, which will be called by the JoinMatchButton. This method will call the ListMatches method from the match maker. The parameters of this method are: the matches page (in our case it is the first page), the number of matches (we only need one match), some filters and the last parameter is the callback (similarly to the CreateMatch method).

Now the callback will be the OnMatchList method. This method will actually call another method from the match maker: JoinMatch. The only important parameters here are the first and the last one. The first one is the match id, which we can get from the listed results. The last parameter is the callback again.

Finally, the last callback (OnMatchJoined) will simply load the Battle Scene. Now, to start the host and the client when the Battle Scene starts, we need two things:

  1. Making the NetworkManager persistent, which means it won’t be destroyed when loading a new scene.
  2. Adding a callback when a new scene is loaded, so that we can start the host and client when that happens.

The first thing is already done by the NetworkManager script, so we don’t need to worry about that. The second thing we are going to do in the Start method. This is done by adding a callback to the sceneLoaded event. The callback (OnSceneLoaded) will only do something when the Battle Scene is loaded. In this case, it removes the callback and checks if this is the host. If so, it starts a new game as the host. Otherwise it starts a new game as the client.

        void Start () {
		SceneManager.sceneLoaded += OnSceneLoaded;

		networkManager.StartMatchMaker ();
	}
	
	private void OnSceneLoaded(Scene scene, LoadSceneMode mode) {
		if (scene.name == "Battle") {
			SceneManager.sceneLoaded -= OnSceneLoaded;
			if (this.isHost) {
				networkManager.StartHost ();
			} else {
				networkManager.StartClient ();
			}
		}
	}

	public void JoinMatch() {
		networkManager.matchMaker.ListMatches (0, 1, string.Empty, true, 0, 0, OnMatchList);
	}

	void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matches) {
		networkManager.matchMaker.JoinMatch (matches [0].networkId, string.Empty, string.Empty, string.Empty, 0, 0, OnMatchJoined);
	}

	void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo) {
		SceneManager.LoadScene ("Battle");
	}

Finally, set the JoinMatch method as the callback of the JoinMatchButton.

By now, you can try playing the game with the Title Screen buttons, and it should still work as with the Network Manager HUD. You can also try using the other parameters of the match maker, such as creating matches with password, using an elo system or listing more matches so that the player can choose one.

And this concludes this multiplayer Bomberman tutorial. Please tell me your opinion and questions in the comments section.

 

]]>
How to Create a Multiplayer Bomberman Game in Unity – Part 2 https://gamedevacademy.org/how-to-create-a-multiplayer-bomberman-game-in-unity-part-2/ Sun, 23 Jul 2017 22:57:26 +0000 https://gamedevacademy.org/?p=5514 Read more]]> In the last tutorial we started adding the basic game features in our Bomberman game. Now, we are going to finish implementing the single player features, such as: dropping bombs, creating explosions and adding a number of lives to the player. Then, in the next tutorial we can add the multiplayer stuff and finish the series.

In order to follow this tutorial, you are expected to be familiar with the following concepts:

  • C# programming
  • Basic Unity concepts, such as importing assets, creating prefabs and adding components
  • Basic Tiled map creation, such as adding a tileset and creating tile layers

Assets copyright

The assets used in this tutorial were created by Cem Kalyoncu/cemkalyoncu and Matt Hackett/richtaur and made available by “usr_share” through the creative commons license, wich allows commercial use under attribution. You can download them in http://opengameart.org/content/bomb-party-the-complete-set or by downloading the source code.

Source code files

You can download the tutorial source code files here.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Dropping bombs

Until now our player can move around the battle map. However, it is still not able to drop bombs in the game. This is what we are going to add now.

The first thing we need to do is creating a Bomb prefab. So, create a new prefab and call it Bomb. This prefab will need a Sprite Renderer, an Animator (you can create one the same way you did for the Player Animator) and a Box Collider 2D. The Box Collider will be a trigger, so check the Is Trigger box. This way, it won’t push the player away from it when the bomb is just dropped. Also, as we did with the other Battle Scene objects, you need to properly set its scale and set the Sorting Layer in the Sprite Renderer to the Game layer.

Now we need to create the Bomb exploding animation. We already created the BombAnimator, so you can create a new animation called Explosion and drag it to the BombAnimator in the Animator editor.

The BombAnimator will be much more simple than the player one. It will only have the Explosion animation, so we don’t need to add any parameters or transitions. But, we still need to create this animation.

In order to easily edit the animation, you can temporarily add a Bomb to the game. So, with the Bomb object selected, open the Animation editor to edit the Explosion animation. Then drag all the bomb spritesheet frames to it, as shown below. Remember to properly set the number of Samples as well. After you finish editing the animation you can remove the Bomb object from the game.

Now that we have a working Bomb prefab, we are going to allow the player to drop bombs in the game.

In order to do that, we are going to create the BombDropping script as below. In the update method of this script we are going to check for the Space key (or any other key you prefer). If this key is pressed, the script is going to call a DropBomb method.

The DropBomb method will instantiate a new Bomb from its prefab (the prefab is an attribute of the script). The position of the new bomb will be the same as the player.

public class BombDropping : MonoBehaviour {

	[SerializeField]
	private GameObject bombPrefab;
	
	// Update is called once per frame
	void Update () {
		if (Input.GetKeyDown ("space")) {
			DropBomb ();
		}
	}

	void DropBomb() {
		Instantiate (bombPrefab, this.gameObject.transform.position, Quaternion.identity);
	}
}

In the end, we add this script to the Player prefab.

And with that, you can already try playing the game and dropping bombs. However, you will notice that the Player is not colliding with the bombs since we configured their colliders as trigger. We are going to fix them now, as we allow the bombs to explode.

Creating explosions

As long as the Bomb collider is a trigger, the Player won’t collide with it. However, we uncheck the Is Trigger box, the Player will be pushed aside when it drops a bomb, since they will collide with each other.

One way of solving this is creating the bomb with a trigger collider. But, once the player is not colliding with the bomb anymore, we change the bomb collider to not be a trigger anymore. From this point the player and the bomb will collide normally.

We are going to do that in a new script called BombExplosion. This script will be used to explode the bomb as well, but for now we are only going to do as below: we are going to implement the OnTriggerExit2D method and, when it is called, it will change the Bomb collider to not be a trigger anymore. The OnTriggerExit2D method is called when another object’s collider leaves the Bomb trigger. So, it will be called once the player is not over the bomb anymore.

public class BombExplosion : MonoBehaviour {

	void OnTriggerExit2D(Collider2D other) {
		this.collider2D.isTrigger = false;
	}
}

Our next step is to explode bombs when their animation ends. Let’s start by creating an Explosion prefab. Then, we can add a Explode method in the BombExplosion script that creates explosions.

So, create a new prefab and call it Explosion. This prefab will have a Sprite Renderer (in the Game Sorting Layer), a Box Collider 2D and a Rigidbody2D. Notice that the Explosion collider will also be a trigger. That’s because we don’t want the explosion to physically interact with other objects, such as the player. However, it needs a Rigidbody2D in order to check for collisions with the walls in the game, because Unity only check for collisions when at least one of the objects has a Rigidbody (another option would be to add a Rigidbody to the walls). However, notice that the Explosion Rigidbody is a Kinematic one, because we don’t want the explosions to move in the game.

Now that we have the Explosion prefab, we can create explosions in the BombExplosion script. So first, let’s create an Explode method as below. First, it will create an explosion in the bomb position. Also, this explosion should be destroyed after some time, so it will call the Destroy method for it with a given explosion duration. Finally, it is going to create explosions in the four directions (left, right, up and down) and destroy itself. The explosions creation is done using a CreateExplosions method, which we are going to implement now.

[SerializeField]
private GameObject explosionPrefab;

[SerializeField]
private float explosionDuration;

public void Explode() {
		GameObject explosion = Instantiate (explosionPrefab, this.gameObject.transform.position, Quaternion.identity) as GameObject;
		Destroy(explosion, this.explosionDuration);
		CreateExplosions (Vector2.left);
		CreateExplosions (Vector2.right);
		CreateExplosions (Vector2.up);
		CreateExplosions (Vector2.down);
		Destroy (this.gameObject);
	}

The CreateExplosions method is shown below. This method will create explosions in a given direction. The number of explosions is given by a explosionRange attribute of the script. So, it is going to iterate from 0 to the number of explosions creating them. However, once it finds a wall or a block, it should stop creating explosions. If it finds a block in this process, the block should be destroyed.

We can do that using the Physics2D.OverlapBox method from Unity. This method receives as parameter a Box, an angle, a ContactFilter and a list of Colliders. Then, it will populate this list of Colliders with all colliders that overlap the queried box. This way, we can check if the region where the explosion will be is already occupied by a wall or a block. In our case, the angle will be 0 and we are not going to use any special ContactFilter, so we should only worry about the box.

The box will be the region the explosion is going to occupy, so we can use the explosionPosition and explosionDimensions values. Once we have the colliders list, we iterate through it looking for walls or blocks. If we find a wall or block, we set a variable as true and break the loop. If we find a block, we destroy it. Finally, in the outer loop, if we have found a block or a wall, we also break this loop. If not, we create a new explosion from the explosionPrefab and set it to be destroyed after the explosion duration.

[SerializeField]
private int explosionRange;

private void CreateExplosions(Vector2 direction) {
		ContactFilter2D contactFilter = new ContactFilter2D ();

		Vector2 explosionDimensions = explosionPrefab.GetComponent<SpriteRenderer> ().bounds.size;
		Vector2 explosionPosition = (Vector2)this.gameObject.transform.position + (explosionDimensions.x * direction);
		for (int explosionIndex = 1; explosionIndex < explosionRange; explosionIndex++) {
			Collider2D[] colliders = new Collider2D[4];
			Physics2D.OverlapBox (explosionPosition, explosionDimensions, 0.0f, contactFilter, colliders);
			bool foundBlockOrWall = false;
			foreach (Collider2D collider in colliders) {
				if (collider) {
					foundBlockOrWall = collider.tag == "Wall" || collider.tag == "Block";
					if (collider.tag == "Block") {
						Destroy(collider.gameObject);
					}
                                        if (foundBlockOrWall) { 
                                                break; 
                                        }
				}
			}
			if (foundBlockOrWall) {
				break;
			}
			GameObject explosion = Instantiate (explosionPrefab, explosionPosition, Quaternion.identity) as GameObject;
			Destroy(explosion, this.explosionDuration);
			explosionPosition += (explosionDimensions.x * direction);
		}
	}

The last thing we need to do is adding a callback in the end of the Explosion animation to call the Explode method. You can do that by opening the Explosion in the animation editor, then right clicking on the last frame and selecting and selecting Add Animation Event. The animation event function will be the Explode method.

And with that, you can try playing the game and letting the bomb to explode. See if the explosions are being correctly created (stopping in the walls and blocks). The next thing we are going to do is allow the explosions to damage other objects, such as the Player and bombs.

Exploding stuff

Explosions should interact with the player and bombs. If an explosion touches the player, it should kill the player. If an explosion touches a bomb, the bomb should explode immediately.

Let’s start by adding the Player lives, so that it can die to a bomb. This will be done using the PlayerLife script below. The script will be responsible for updating the current number of lives, but also for making the player invulnerable for a short time right after it has been damaged. This prevents the player to be exploded by multiple bombs at once.

So, the LoseLife method starts by checking if the player is not currently invulnerable. If it is vulnerable, it will reduce the current number of lives and check if this was the last life. If so, it will also destroy the player object. After decreasing the number of lives, it will make the player invulnerable, and invoke the BecomeVulnerable method after the invulnerability duration time. The BecomeVulnerable method, by its turn, will simply make the player vulnerable again.

public class PlayerLife : MonoBehaviour {

	[SerializeField]
	private int numberOfLives = 3;

	[SerializeField]
	private float invulnerabilityDuration = 2;

	private bool isInvulnerable = false;

	public void LoseLife() {
		if (!this.isInvulnerable) {
			this.numberOfLives--;
			if (this.numberOfLives == 0) {
				Destroy (this.gameObject);
			}
			this.isInvulnerable = true;
			Invoke ("BecomeVulnerable", this.invulnerabilityDuration); 
		}
	}

	private void BecomeVulnerable() {
		this.isInvulnerable = false;
	}
}

Now we are going to create a script for the Explosion which will call the LoseLife method when colliding with the player. This script will be called ExplosionDamage, and it is shown below. We are going to implement the OnTriggerEnter2D method, which will be called every time another object collides with the explosion. When this happens, we are going to check the type of the object by its tag (remember to properly set the prefabs tags). If it is a “Character” tag, it will call the LoseLife method in the PlayerLife script. If it is a “Bomb” tag, it will call the Explode method in the BombExplosion script. This Explode method is the same we were already using, so we don’t need to implement a new one.

public class ExplosionDamage : MonoBehaviour {

	void OnTriggerEnter2D(Collider2D collider) {
		if (collider.tag == "Character") {
			collider.gameObject.GetComponent<PlayerLife> ().LoseLife ();
		} else if (collider.tag == "Bomb") {
			collider.gameObject.GetComponent<BombExplosion> ().Explode ();
		}
	}
}

Then, we add those scripts to their respective prefabs.

By now, you can already try playing and checking if the explosions interacting correctly with the Player and the Bombs. However, we still can not see in the game the current number of player lives. This is the next thing we are going to do.

Showing the player lives

Similarly to how we showed the title and text in the title screen, we are going to create a Canvas to show the player number of lives. Let’s start by creating a new Canvas (right-click on the Hierarchy, then UI->Canvas) and calling it HUDCanvas. This Canvas will be configured the same way we did with the BackgroundCanvas:

  • Set Render Mode to Screen Space – Camera
  • Select the Main Camera as the Render Camera
  • Select the Sorting Layer as Game
  • Set UI Scale Mode as Scale With Screen Size

Now we are going to create an object which will represent a grid to show the player lives. We can do that by creating an empty object as a child of the Canvas, and then adding a Grid Layout Group component to it. Then, we need to properly configur this Grid Layout Group to show the player lives the way we want.

Basically, what we need to do is changing the Constraint field to Fixed Row Count, and Constraint Count to 1. This will make the grid to show the lives in a single row. Also, we need to change the Cell Size to 20×20. Figure below shows the PlayerLivesGrid object.

Now we need to create objects to represent the player lives, and manage them in the lives grid. So, let’s create a new Image as a child of the HUDCanvas, calling it PlayerLifeImage and making it a prefab. In this image, we just need to set the Source Image to be the heart sprite.

Now, we are going to change the PlayerLife script to manage the player lives in the grid. First, we need to add two new attribute: one attribute for the player life image prefab, and another one with a List, storing all player life images. Then, in the Start method we create a PlayerLifeImage object for each one of the player lives. Notice that we need the PlayerLivesGrid object so that we can create the images as children of it. After creating each image, we add it to the lifeImages list.

We also need to change the LoseLife method to destroy a PlayerLifeImage when the player loses a life. We can do that by retrieving the last element from the lifeImages list, destroying it, and then removing it from the List.

public class PlayerLife : MonoBehaviour {

	[SerializeField]
	private int numberOfLives = 3;

	[SerializeField]
	private float invulnerabilityDuration = 2;

	private bool isInvulnerable = false;

	[SerializeField]
	private GameObject playerLifeImage;

	private List<GameObject> lifeImages;

	void Start() {
		GameObject playerLivesGrid = GameObject.Find ("PlayerLivesGrid");

		this.lifeImages = new List<GameObject> ();
		for (int lifeIndex = 0; lifeIndex < this.numberOfLives; ++lifeIndex) {
			GameObject lifeImage = Instantiate (playerLifeImage, playerLivesGrid.transform) as GameObject;
			this.lifeImages.Add (lifeImage);
		}
	}

	public void LoseLife() {
		if (!this.isInvulnerable) {
			this.numberOfLives--;
			GameObject lifeImage = this.lifeImages [this.lifeImages.Count - 1];
			Destroy (lifeImage);
			this.lifeImages.RemoveAt (this.lifeImages.Count - 1);
			if (this.numberOfLives == 0) {
				Destroy (this.gameObject);
			}
			this.isInvulnerable = true;
			Invoke ("BecomeVulnerable", this.invulnerabilityDuration); 
		}
	}

	private void BecomeVulnerable() {
		this.isInvulnerable = false;
	}
}

Now, we can already play the game and see the player lives in the screen. The last thing we are going to do in this tutorial is adding a Game Over message when the player loses all its lives.

Game over message

The game over message will be a text shown in the HUD Canvas when the player loses all its lives. So, let’s start by creating those texts in the HUD Canvas.

First, in order to easily enable and disable texts, we are going to group them in an object. So, start by creating an empty object called GameOverPanel. Then, we are going to attach the StartGame script to it. The StartGame script is the same we used in the Title Scene, and we are going to use it again here since we want to restart the game after the game is over.

Now we add two Texts (UI->Text) as children of the GameOverPanel. The first one will be called GameOverMessage and will show the Text “Game Over!”. The second one will be called RetryMessage and will show the Text “Press any key to retry”. You can change the font size to be the way you prefer.

Also, in order to make sure the HUDCanvas will appear above everything else, you can create another Sorting Layer called HUD and assign the Canvas to it.

Now, we disable the GameOverPanel by unchecking the box next to its name. We do this because we we want the GameOverPanel to appear only when the player loses the game.

Finally, we change the PlayerLife script to show the GameOverPanel when its game over. We do this by adding the GameOverPanel as an attribute of the script. Then, in the LoseLife method, when the current number of lives is equal to 0 we set the panel as active.

[SerializeField]
private GameObject gameOverPanel;

public void LoseLife() {
		if (!this.isInvulnerable) {
			this.numberOfLives--;
			GameObject lifeImage = this.lifeImages [this.lifeImages.Count - 1];
			Destroy (lifeImage);
			this.lifeImages.RemoveAt (this.lifeImages.Count - 1);
			if (this.numberOfLives == 0) {
				Destroy (this.gameObject);
				this.gameOverPanel.SetActive (true);
			}
			this.isInvulnerable = true;
			Invoke ("BecomeVulnerable", this.invulnerabilityDuration); 
		}
	}

Now, you can try playing the game and dying, to see if the game over message is being correctly displayed. Also, check if you can restart the game.

And this concludes the single player features of our game. In the next tutorial we are going to make our game multiplayer, adding two players in a battle!

 

 

]]>
How to Create a Multiplayer Bomberman Game in Unity – Part 1 https://gamedevacademy.org/how-to-create-a-multiplayer-bomberman-game-in-unity-part-1/ Fri, 14 Jul 2017 01:21:36 +0000 https://gamedevacademy.org/?p=5465 Read more]]> In this tutorial series we are going to build a multiplayer Bomberman game. Our game will have a title scene, which will allow the players to create or join games. Also, it will have a battle scene, where the players will fight each other in a competitive mode.

In this first tutorial we will build the basic infrastructure for our game, such as the Title and Battle scenes, as well as adding the player in our game. In the next ones we are going to keep adding features to it.

In order to follow this tutorial, you are expected to be familiar with the following concepts:

  • C# programming
  • Basic Unity concepts, such as importing assets, creating prefabs and adding components
  • Basic Tiled map creation, such as adding a tileset and creating tile layers

Before starting reading the tutorial, create a new Unity project and import all sprites available through the source code.

BUILD GAMES

FINAL DAYS: Unlock 250+ coding courses, guided learning paths, help from expert mentors, and more.

Assets copyright

The assets used in this tutorial were created by Cem Kalyoncu/cemkalyoncu and Matt Hackett/richtaur and made available by “usr_share” through the creative commons license, wich allows commercial use under attribution. You can download them in http://opengameart.org/content/bomb-party-the-complete-set or by downloading the source code.

Source code files

You can download the tutorial source code files here.

Slicing spritesheets

Once you have imported the sprites from the source code, you will notice that some of those sprites are simply images, while others are spritesheets. The images are already good to be used, but we need to slice the spritesheets into frames.

The way we do that is by selecting the spritesheet in the editor, then changing its Sprite Mode to multiple. Then we can click in the Sprite Editor button to slice it.

Once you have opened the Sprite Editor window, the slice button will show the slice options. Usually, we can slice them using the Automatic Type and hitting the Slice button, which will find the best separation for each frame. You can use this slice Type for the bomb and player spritesheets.

However, for slicing the tileset, selecting the Automatic Type doesn’t work, because some of the tiles are too close, and are too similar too each other. So we are going to select the Grid By Cell Size Type. The cell size for this tileset is 16×16. Finally, we hit the Slice button.

Now that we have configured all our game sprites, we can start building the game scenes, starting by the Title Scene.

Title scene

In this tutorial, the Title Scene will be very simple. It will simply show the game title, and a message to start the game. Then, we are going to add a script to start the game when the player presses any key. In order to show the game title and the message, we are going to need to create a Canvas.

Title canvas

A Canvas in Unity is a object where you can put your UI elements, such as texts, images and buttons. In order to create a canvas, simply right-click on the objects hierarchy, then go to UI->Canvas. We are going to call this object TitleCanvas.

We need to configure some properties in the Canvas object. First, we are going to set the Render Mode to Screen Space – Camera, and we are going to select our Main Camera as the Render Camera. Also, we are going to change the UI Scale Mode to Scale With Screen Size, so that our canvas behaves well as the game screen size changes.

Now that we have our canvas, we are going to add its elements. First, let’s add a BackgroundImage, but adding a new Image as a child of the Canvas (UI->Image). We are not going to select any source image for the background, but we are going to set its color as black.

The second child of the BackgroundCanvas will be another image, but this one will be called GameTitle. The game title will be an image from our sprites folder, so select it as the Source Image of the GameTitle object.

Finally, we are going to add a Text as child of the Canvas (UI->Text), which will be called StartGameText. In this object we need to set its text content and font properties. The figure below shows the settings I used, but you can choose the ones that look better in your game.

Now that we have all the objects in our Title Scene, we only need to add an event to start the game when the player presses any key.

Start game

We are going to start the game using a very simple script, as below.

We only need to implement the Update method of this script and, in this method we check if any key has been pressed (Input.anyKey is true). If so, we load a scene called Battle. However, in order to call this LoadScene method, you need to use the SceneManagement namespace in your script, so remember to do that.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class StartGame : MonoBehaviour {

	void Update () {
		if (Input.anyKey) {
			SceneManager.LoadScene ("Battle");
		}
	}
}

After creating the script, we add it to the StartGameText object.

However, if you try running the game it will still not open the next scene. In order to do so, we need to:

  1. Create a new scene called Battle
  2. Add both scenes (Title and Battle) in the Build list of our game

The first thing is easy. Simply create a new empty scene and call it Battle. Now, for the second thing we need to go to File->Build Settings. Then, then you can drag and drop both scenes to the Scenes in Build part of the Build Settings window.

By now, you should be able to run the Title Scene and start the game.

Our next step will be to create the Battle Scene.

Battle scene

The Battle scene will be where all the gameplay happens. Player will be able to move through the scene dropping bombs. Each bomb will explode after some time, creating explosions. Explosions can destroy blocks, but not walls. If an explosion hits a player, the player dies. Also, if an explosion hits a bomb, it makes the bomb to instantly explode.

The first thing we need to do in our Battle Scene, is creating our battle map.

Creating and importing the Tiled map

We are going to create a Tiled map for our Battle Scene. In order to do that, we are going to use the Tiled map editor.

Since building maps in Tiled is not the objective of this tutorial, I’m not going to explain the details of how to build our battle map using it. So, feel free to use the map provided in the source code (shown below) or to create your own. However, if you create your own map, you should be careful with two things:

  1. I’m only adding tile layers for the background and for the walls. Other objects, such as the player and blocks will be added later in Unity.
  2. In order to properly have colliders for the walls, we need to configure some tile colliders accordingly. You can do this by selecting the tiles that should be collidable (for example the wall tiles) and selecting Tile->Tile Collision Editor. This will open a window like the one below, where you can configure the collision area of the tile.

After creating the map, you can save it using the Tiled map format and add it to a Maps folder in your Unity project.

However, we can’t simply open this map in Unity. We are going to need another tool to convert it to a Unity object, so that we can add it in our game.

We are going to use the Tiled2Unity tool for that. This tool receives as input a Tiled map and creates a Unity object in your game representing the map. In this process it also creates the colliders for tiles when necessary.

After installing Tiled2Unity you will find two important files in its installation folder: the Tiled2Unity executable file and the Tiled2Unity Unity package.

First, open the Tiled2Unity Unity package, so that it will be imported in your Unity project. This will create a Tiled2Unity folder in your Assets folder, with a Tiled2Unity.export file inside of it (among many other files and folders). This file will be important later to import your map.

Now, open the Tiled2Unity executable file. This will open a window like the one below, where you can select your map to import to Unity. The Export To location is the Tiled2Unity.export file mentioned earlier.

You can also preview your map before exporting. This should show the colliders of the walls.

After you export your map to Unity, it will create a prefab for it in the Tiled2Unity/Prefabs folder. Then, you can add this prefab to your game. However, you will need to change its scale, since it will be too big for the game screen, as it is.

And with that we have finished importing our Tiled map in our Unity project. Now, we are going to add other objects to our Battle Scene. Starting with blocks, which will be exploded with the bombs.

Adding blocks

Let’s start by creating a prefab for the block. The block will simply have a Sprite Renderer and a Box Collider. The sprite will be one from the tileset. However, notice that we are setting the Sorting Layer of the Sprite Renderer as Game. This is a custom layer you need to create, so that the blocks appear above the map.

Then, we are going to add an empty object as child of the BattleMap. This empty object will be called blocks, and it will group all the blocks.

Now, we can add Block prefabs in our game, and make them children of the blocks object. You can put the blocks whenere you wish (the figure below shows an example). However, be aware that you need to properly set the block scale, so that it appears in a reasonable size.

Now that we have the walls and the blocks, we are going to create the Player object of our game.

Moving the player

The first thing we need to do is creating a Player prefab, and allowing it to navigate through the map.

So, create a new Prefab called Player with a Sprite Renderer, a Rigidbody 2D (so that we can control its velocity), and a Box Collider 2D (to check for collisions). Also, you will need to adjust its scale, so that it has a reasonable size in our battle map.

Now, we are going to create a new Script called Player Movement as below. The script gets the movement axis (horizontal and vertical) in order to determine the player velocity in both directions. The way the player moves is as follows: the player can move to a given direction (for example, to the left), if it is not already moving to the opposite direction (to the right).

So, the first condition in the script checks if the player velocity is less than or equal to zero (which means the player is not moving to the right). If so, we can change its velocity in the X axis to make it move left. We do the same for all directions. In the end, we set the player object velocity.

public class PlayerMovement : MonoBehaviour {

	[SerializeField]
	private float speed;

	void FixedUpdate () {
		float moveHorizontal = Input.GetAxis ("Horizontal");
		float moveVertical = Input.GetAxis ("Vertical");

		Vector2 currentVelocity = gameObject.GetComponent<Rigidbody2D> ().velocity;

		float newVelocityX = 0f;
		if (moveHorizontal < 0 && currentVelocity.x <= 0) {
			newVelocityX = -speed;
		} else if (moveHorizontal > 0 && currentVelocity.x >= 0) {
			newVelocityX = speed;
		} 

		float newVelocityY = 0f;
		if (moveVertical < 0 && currentVelocity.y <= 0) {
			newVelocityY = -speed;
		} else if (moveVertical > 0 && currentVelocity.y >= 0) {
			newVelocityY = speed;
		}

		gameObject.GetComponent<Rigidbody2D> ().velocity = new Vector2 (newVelocityX, newVelocityY);
	}
}

Now, we add this script to the Player prefab, and if you try playing the game now, you can already move the player. However, it is still not playing its walking animations. So, our next step will be to add the player animations and their transitions.

Animating the player

In order to add animations in Unity, the first thing we need to do is creating an Animator Controller. What I’m going to do is creating a new folder in Assets/Animations/Player and then I’m going to create a new Animator Controller called PlayerAnimator (you can create the Animator by clicking on Create->Animator Controller). Then, we can add this Animator to the Player prefab.

Now we are going to create the Player animations. The Player will have eight animations: four idle animations (one for each direction) and four walking animations (one for each direction).

Once you have created all Animations (you don’t need to set the animation frames yet), we are going to add them to the PlayerAnimator. So, with the Player prefab selected, open the Animator editor in Unity. This will show the Animator state machine. Then, drag and drop the animations to the Animator. Now, if you switch to the Animation editor, you can set the frames for each animation. This will create a state for each animation.

The idle animations will only show the player standing in a given direction, so they will have only one frame. The walking animations will have the frames for that walking movement. The figures below show the examples for the IdleLeft and WalkingLeft animations. You can create the other ones in a similar way. However, notice that you need to properly set the number of Samples in the animations.

We want an animation to play when the player is moving to that direction, so the Animator state will be controlled by the PlayerMovement script. We can control an animator by adding parameters to the Animator (in the Parameters tab of the Animator editor). We are going to add two parameters: DirectionX and DirectionY. Each parameter will be an integer between -1 and 1, and will tell to the Animator if the player is moving to a given direction. For example, if the DirectionX parameter is equals to 1, the player should transition to the WalkingRight animation.

Now we need to create the transitions between animations using the parameters. There will be three types of transitions:

  1. If the Player is stopped and starts moving to any direction, it should start playing the animation of that direction. So, we need transitions between each Idle state to each Walking state. The parameters of the transition will depend on the direction the player is moving to.
  2. If the Player is moving in a given direction, and both DirectionX and DirectionY parameters become 0, it should go back to an IdleState. The correct idle state depends on the current walking animation. For example, if the current animation is WalkingLeft, it will go back to the IdleLeft state.
  3. If the Player is moving in a given direction, and the DirectionX or DirectionY parameters change, it should go to a different walking animation. For example, if the current animation is WalkingLeft, but eventually DirectionX become 0 and DirectionY become 1, it should transition to the WalkingUp animation.

Adding all those transition rules, the PlayerAnimator should look like this in the end:

However, there are still some details we need to fix in our animations. First, the walking animations should loop when they end. So, select those animations, and check the Loop Time box.

Also, in order to have more smooth transitions between the animations, we are going to set the delay between them to 0. We can do that by selecting a transition, then checking the Has Exit Time and Fixed Duration boxes and setting the Transition Duration to 0.

Finally, we need to set the DirectionX and DirectionY parameters in the PlayerMovement script. This will be done as shown below. Once we set the velocity in a given direction, we update the DirectionX or DirectionY parameter accordingly. If the player is not moving in a given axis, we set its direction parameter to 0.

public class PlayerMovement : MonoBehaviour {

	[SerializeField]
	private float speed;

	[SerializeField]
	private Animator animator;

	void FixedUpdate () {
		float moveHorizontal = Input.GetAxis ("Horizontal");
		float moveVertical = Input.GetAxis ("Vertical");

		Vector2 currentVelocity = gameObject.GetComponent<Rigidbody2D> ().velocity;

		float newVelocityX = 0f;
		if (moveHorizontal < 0 && currentVelocity.x <= 0) {
			newVelocityX = -speed;
			animator.SetInteger ("DirectionX", -1);
		} else if (moveHorizontal > 0 && currentVelocity.x >= 0) {
			newVelocityX = speed;
			animator.SetInteger ("DirectionX", 1);
		} else {
			animator.SetInteger ("DirectionX", 0);
		}

		float newVelocityY = 0f;
		if (moveVertical < 0 && currentVelocity.y <= 0) {
			newVelocityY = -speed;
			animator.SetInteger ("DirectionY", -1);
		} else if (moveVertical > 0 && currentVelocity.y >= 0) {
			newVelocityY = speed;
			animator.SetInteger ("DirectionY", 1);
		} else {
			animator.SetInteger ("DirectionY", 0);
		}

		gameObject.GetComponent<Rigidbody2D> ().velocity = new Vector2 (newVelocityX, newVelocityY);
	}
}

By now, you can try playing the game and moving the player. Check if all animations are playing correctly, and if the player is correctly colliding with the walls.

And this concludes this part of this tutorial series. In the next part we are going to allow the player to drop bombs, as well as making the bombs to explode and destroy blocks in the game. 

]]>