Turn Based Multiplayer – Part 1

In this project, we will be using Unity’s new networking libraries to make a turn-based multiplayer game. I chose a very simple game, TicTacToe, so that I woudn’t be too distracted by much beyond the architecture I would need to achieve my goal. It is my first attempt to implement networking with Unity, so I am very open to feedback. If the general response is positive, then I may take it a bit further and try to make a Hearthstone sytle card game.

Getting Started

The completed project is available here as a git repository. You can use this to download the project in its final form, or to see how the project looked at each step of its creation – there is one commit for each lesson. Feel free to download and try out the project, or read along and create it from scratch.

Project Setup

Open Unity (this series was created using Unity version 5.3.1) and create a new project. There are several scripts I want to reuse from my other projects which I have provided as a unitypackage here. Download and import the package into your new project. Make sure that all assets are checked for import and click “Import”.

 photo TicTacToeAssetImport_zpshjjwp97g.png

Scene Setup

One of the first things I do when beginning a new project is to rough out some assets that will be needed. I lovingly call this “programmer art” because it isn’t intended to go in a finished product but does need to be there so development can continue. For this project we will need some way to represent a Tic Tac Toe board, as well as the pieces that indicate the player marks. In addition, we will add some User Interface (UI) elements.

 photo TTT_Scene_Setup_zpssatqi0ju.png

Create an ‘X’ Mark

  1. Create an Empty GameObject and name it “Mark X”
  2. Create a cube
  3. Parent the cube to the “Mark X” GameObject
  4. Rotate the cube to rotation (Y: 45)
  5. Size the cube to scale (X: 0.15, Y: 0.2, Z: 0.6)
  6. Duplicate the cube
  7. Rotate the duplicate cube to rotation (Y: 315)

 photo TTT_Mark_X_zpsg7dg4s4j.png

We’re going to need to make this into a prefab so we can easily create several instances of the mark on the board:

  1. Create a new Project Folder named “Prefabs”
  2. Drag the “Mark X” object from the Hierarchy pane onto the “Prefabs” folder in the Project pane to create a prefab from it
  3. Delete the “Mark X” instance from the scene

Create an ‘O’ Mark

  1. Create an Empty GameObject and name it “Mark O”
  2. Create a sphere
  3. Parent the sphere to the “Mark O” GameObject
  4. Size the sphere to scale (X: 0.6, Y: 0.3, Z: 0.6)
  5. Create a prefab out of “Mark O”
  6. Delete the “Mark O” instance from the scene

 photo TTT_Mark_O_zpsi19obkty.png

Poolers

Now let’s go ahead and create the poolers which will allow us to instantiate and then reuse a collection of our marks.

  1. Create an empty GameObject named “X Pooler”
  2. Add the “Set Pooler” component to this object
  3. Look in the inspector at the settings for the “Set Pooler” component
  4. Assign the prefab field to use the “Mark X” prefab
  5. Tell the pooler to prepopulate with 5 instances
  6. Duplicate the “X Pooler”
  7. Rename the duplicate to “O Pooler”
  8. Configure the duplicate to use the “Mark O” prefab
  9. Reduce the duplicate’s prepoulate count to 4 instances

In this project I always let ‘X’ go first (regardless of the controlling player) which is why it gets five instances and the ‘O’ only gets four. Add them together and you have 9 marks, which is the total number I need to completely fill the Tic Tac Toe board.

Note that I skipped a few settings on the pooler because they weren’t necessary given the simplicity of this project. For example, I could have specified a “Key” for the pooler to use, but since it defaults to using the name of the prefab as its key, that was sufficient for now. Likewise I could have reduced the “Max Count” of the pooler to be the same value as the “Prepopulate” field, but I know I wont be generating more than I expect so it wasn’t necessary. I didn’t need to specify a prepopulate count either, but specifying it is more efficient than needing to resize the collection as we play.

Create the Board

  1. Create an empty GameObject named “Board”
  2. Add a Box Collider component
  3. Set the collider Center to (X: 1.5, Y: 0, Z: 1.5)
  4. Set the collider Size to (X: 3, Y: 0.1, Z: 3)
  5. Create a cube
  6. Rename the cube to “Surface”
  7. Parent the cube to the Board
  8. Move the cube to Position (X: 1.5, Y: 0, Z: 1.5)
  9. Size the cube to Scale (X: 3, Y: 0.1, Z: 3)
  10. Remove the Box Collider from the cube

If you are wondering why I created a separate container GameObject for the board with its own collider instead of just using the Cube that shows its surface, it is because I like the scale to be left at 1. Since I had to scale the cube which represents the surface of the board, any objects which are parented to it would also be scaled and the numbers are less intuitive to work with. Furthermore, with this hierarchy I could easily replace the “visual” portion of the object later with something nicer.

Now I want to give the game board a little color so that the lines and marks will stand out a little better:

  1. Create a new Project folder named “Materials”
  2. Create a new Material in that folder named “Board”
  3. Set the Albedo Color (R: 140, G: 163, B: 176)
  4. Drag the Material onto the Board’s cube surface in the scene

Next, let’s create the lines which help to visually separate the nine squares of the board:

  1. Create a cube
  2. Rename the cube to “Line”
  3. Parent the cube to the Board
  4. Move the cube to Position (X: 1, Y: 0, Z: 1.5)
  5. Size the cube to Scale (X: 0.02, Y: 0.11, Z: 3)
  6. Duplicate this line 3 times
  7. Move the first duplicate to Position (X: 2)
  8. Move the second duplicate to Position (X: 1.5, Z: 1)
  9. Rotate the second duplicate to Rotation (Y: 90)
  10. Move the third duplicate to Position (X: 1.5, Z: 2)
  11. Rotate the third duplicate to Rotation (Y: 90)

Let’s go ahead and keep the mark poolers as part of the Board hierarchy since they are related to it.

  1. Parent the “X Pooler” to the “Board”
  2. Parent the “Y Pooler” to the “Board”

Since we don’t need to create multiple instances of the Game Board you might think we don’t need to create a prefab out of it. In a way that’s true, as long as we save the scene we will have everything we need for this simple demo. However, I still like to create prefabs out of important objects. Especially when working on teams and using version control. By using a prefab, I will be able to make future changes to the Game Board without needing to modify the scene, and that practice allows teams to have less working conflicts among each other.

  1. Create a prefab out of the “Game Board” – but this time don’t delete the instance in the scene.

Camera

Now let’s position the camera so that we will have a good view of the board. I decided to leave a little perspective in there but of course that is an optional feature:

  1. Move the “Main Camera” to Position (X: 1.5, Y: 3, Z: -0.15)
  2. Rotate the “Main Camera” to Rotation (X: 60)
  3. In order to detect clicks or taps on the board, add a “Physics Raycaster” component to the “Main Camera” GameObject.

Create the User Interface (UI)

Our UI isn’t very demanding. All I want is three labels: one to show game state, and one for each player to indicate which mark they are controlling and how many times they have won.

  1. Create a Canvas
  2. Create a Text as a child of the Canvas
  3. Look in the Inspector for the “Rect Transform” component of the Text object
  4. Hold Alt & Shift to set the anchor and pivot preset simultaneously to “Top Center” position
  5. Move the Text to Position (Y: -20)
  6. Find the “Text” component beneath the “Rect Transform” component in the inspector
  7. Set the Font Size to 30
  8. Set the Color to White
  9. Add a “Content Size Fitter” component
  10. Set the “Horizontal Fit” and “Vertical Fit” to “Preferred Size”
  11. Rename this Text object to “Game State Label”
  12. Duplicate the Text
  13. Rename the duplicate to Local Player Label
  14. Hold Alt & Shift to set the anchor and pivot preset simultaneously to “Bottom Left” position
  15. Move the Text to Position (X: 10, Y: 10)
  16. Set the Font Size to 14
  17. Duplicate the “Local Player Label”
  18. Rename this duplicate to “Remote Player Label”
  19. Hold Alt & Shift to set the anchor and pivot preset simultaneously to “Bottom Right” position
  20. Move the Text to Position (X: -10, Y: 10)
  21. Set the Horizontal Text Alignment to “Right” justified
  22. Create a prefab from our Canvas

Save

Before we finish we need to make sure and save both the scene and the project:

  1. Create a new Project folder named “Scenes”
  2. Save your scene in the “Scenes” folder as “Main”
  3. Save your project

Summary

In this lesson we prepared the project by importing some reusable code. Then we created a few simple assets which would be necessary to represent and interact with a game of TicTacToe such as the game board, the marks that are placed on it, and some UI that will help indicate what to do.

Don’t forget that if you get stuck on something, you can always check the repository for a working version here.

4 thoughts on “Turn Based Multiplayer – Part 1

  1. Do you happen to have a tutorial on your NotificationCenter code? Seems like a pretty good command queue system.

    1. I use it in several projects, such as in the Tactics RPG. I like the library and would use it on the Pokemon Board Game, but part of me wants to reduce the number of libraries that a new user would have to learn in order to follow along.

  2. Quick feedback: The inclusion of 3D object modelling and the requirement to download a pre-written set of scripts to handle high-level functionality had the effect of clouding the main point of the tutorial: How to create a turn-based multiplayer game. It would be helpful to see a step-by-step walkthrough that focused on creating the essential structures for managing network and turns. Now I have to pry apart the scripts to learn what I want, which is ironic since the point of a tutorial is to avoid that.

    1. Just want to point out that I do perform a step-by-step walkthrough during this series – I hope you didn’t stop reading on the first page. I’m sorry you don’t enjoy this post, I had imagined that at least “some” visual feedback would be very helpful in knowing that things were working, and this felt like the simplest visual feedback I could create.

Leave a Reply to Marko Cancel reply

Your email address will not be published. Required fields are marked *