Lap trinh game nhieu nguoi choi,ung dung da nen tang,game nhieu nguoi choi,lap trinh game android,lap trinh ung dung android,lap trinh ung dung,viet app android,ky thuat lap trinh,ky thuat ung dung game
Trang 2Unity Multiplayer Games
Build engaging, fully functional, multiplayer games with Unity engine
Alan R Stagner
BIRMINGHAM - MUMBAI
Trang 3Unity Multiplayer Games
Copyright © 2013 Packt Publishing
All rights reserved No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews
Every effort has been made in the preparation of this book to ensure the accuracy
of the information presented However, the information contained in this book is sold without warranty, either express or implied Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals However, Packt Publishing cannot guarantee the accuracy of this information.First published: December 2013
Trang 5About the Author
Alan R Stagner is an independent developer with a passion for Unity3D game
development He was introduced to programming by his father, he sought out different ways to create games in a variety of languages Most recently, he found the Unity game engine and was instantly hooked, and discovered his love of multiplayer game development He has also dabbled in database and server programming from time to time, mostly involving PHP and MySQL with recent forays into ASP.NET
I'd like to thank my family and friends, of course—my father is the
entire reason I'm a programmer and has helped me every step of
the way Everyone I know has been incredibly supportive I'd like
to thank the Unity community—without them I don't think I would
know Unity like I do today I'd also like to thank Unity for providing
such an awesome platform and making it so easy for me to write my
first multiplayer game
Trang 6About the Reviewers
Clifford Champion has a broad background in software engineering, with years
of experience spanning 3D games and Internet applications, and more recently in machine learning He holds a degree in Mathematics from UCLA In the past, he has worked as an integration and support engineer at Havok, and also as a lead interactive media and Internet apps programmer at PlainJoe Studios
Now, he works for zSpace (zspace.com), a hardware/software company
creating highly immersive, interactive 3D displays for classrooms, industry, and entertainment At zSpace, he is a member of the software platform team, helping to enable the holographic-like experience on a variety of game engines and platforms, including Unity Clifford can be found on Twitter at @duckmaestro and welcomes any discussions
Fabio Ferrara is a game developer He is working for Chubby Pixel, an
independent game studio based in Milan, which he founded in 2012 They work thoroughly to bring to the users the best possible gaming experience He has also
collaborated for the publication of other books such as Unity iOS Essentials,
Packt Publishing.
Sriram A S is a software developer who is currently living in Pune, India He
works primarily in C/C++ and Java He has been working with Unity 3D from its very early versions; and has developed codes related to its integration with
features such as augmented reality, and shared them on his tech blog
(http://mypersonalsoft.blogspot.com)
In his spare time, he works on a few open source software And he also likes to experiment with various other technologies and ideas, along with his team of code passionate friends—the "Hobby Coders" (http://hobbycoders.com)
Trang 7Support files, eBooks, discount offers, and more
You might want to visit www.packtpub.com for support files and downloads related
to your book
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packtpub.com and as a print book customer, you are entitled to a discount on the eBook copy Get in touch with us at service@packtpub.com for more details
At www.packtpub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers
on Packt books and eBooks
TM
http://PacktLib.PacktPub.com
Do you need instant solutions to your IT questions? PacktLib is Packt's online digital book library Here, you can access, read and search across Packt's entire library of books
Why Subscribe?
• Fully searchable across every book published by Packt
• Copy and paste, print and bookmark content
• On demand and accessible via web browser
Free Access for Packt account holders
If you have an account with Packt at www.packtpub.com, you can use this to access PacktLib today and view nine entirely free books Simply use your login credentials
Trang 8Table of Contents
Preface 1
Setting up a server console without Pro 23
Displaying the score to the player 37
Trang 9Table of Contents
Chapter 2: Photon Unity Networking – The Chat Client 53
Adding friends lists 76
Trang 11Table of Contents
Trang 12This book intends to step you through the concepts and middleware involved
in creating multiplayer games with the Unity game engine I've been a big fan of multiplayer games for a while They have a way of tapping into our basic desires, fulfilling a need to compete, to co-operate, and most of all to socialize with our fellow humans, in a way that no single player game can ever provide
I've experienced a wide range of networking plugins and applications in Unity As
I learn new networking systems, there are always stumbling blocks and difficult issues I wrote this book because I wanted to help others on the same path, and help them surmount the issues I encountered myself
Unity IDE crash course
To better understand this book, we'll need to cover the basic features of the
Unity IDE
If you open Unity for the first time, you'll be presented with a window where you
can either open an existing project or create a new one Select the Create New Project
tab, and choose a location for your project
Once your project is created, you'll see a number of panels There are the Scene and
Game tabs, the Hierarchy, Project, and Console tabs, and the Inspector tab.
The Scene view shows the current scene This will allow you to navigate the scene, select objects, move them around, and more The Game view shows the view of the main camera If you press the Play button, the Game view is automatically shown
and allows you to play test your game from inside the editor
The Hierarchy tab shows the object hierarchy of the current scene This allows you to
select objects, parent or unparent them, delete them, rename them, and much more
Trang 13The Inspector tab shows the editors for each component attached to the selected
object (rather than being inheritance based like many traditional engines, Unity is component based, where objects are a collection of components and each component has a separate responsibility) It allows you to set values and change properties of components You can also remove components by right clicking on a component and
clicking on Remove Component In Unity 4 and later, you can also click on the Add
Component button and select a component script.
The Project tab shows the assets in your project You can drop game assets here to
import them, and you can create new materials, scripts, and shaders by right-clicking
and selecting the Create option You can also drag objects from the Hierarchy to the Project tab to create a prefab Prefabs are essentially object templates—you can
Instantiate a prefab to create an exact copy of the prefab in the scene (for instance,
you might create an Enemy prefab, and instantiate it to spawn enemies) You can also drag component scripts from the Project to the Inspector of a selected game object to add the component to the object
To learn more about Unity, you can get started here:
http://unity3d.com/learn
What this book covers
Chapter 1, Unity Networking – The Pong Game, introduces the concept of reliable UDP
communication, and different types of servers employed by games It covers Unity Networking, and creating a networked two-player Pong clone
Chapter 2, Photon Unity Networking – The Chat Client, covers a third-party alternative
to Unity Networking It introduces the concept of the cloud-hosted game servers, simple matchmaking, and friends lists It also covers the creation of a simple
chat client
Chapter 3, Photon Server – Star Collector, introduces dedicated servers for games
It covers creating a Photon Server application, connecting to a server, using the request/response/event system to communicate, and creating a simple Star
Collector game
Chapter 4, Player.IO – Bot Wars, covers an alternative dedicated server system It
introduces the database features of Player.IO, how to create a Player.IO server, connecting from Unity, and creating a simple RTS-style game with persistent
user stats
Trang 14[ 3 ]
Chapter 5, PubNub – The Global Chatbox, introduces communication over an HTTP
messaging service It covers benefits and pitfalls of HTTP for communication, using the WWW class to communicate via PubNub, and creating a chatroom application
Chapter 6, Entity Interpolation and Prediction, introduces the concept of server-side
movement physics and potential issues and solutions It covers client-side movement prediction, and how to smooth the motion of remote entities
Chapter 7, Server-side Hit Detection, introduces the concept of server-side hit detection
for shooter-style games It covers the reasons behind target-leading problems in many online games, and how to resolve the issue by rewinding the game state
What you need for this book
You will need Unity 3 or later for this book Many chapters require specific downloads:
• Chapter 2, Photon Unity Networking – The Chat Client, requires the Photon
Unity Networking plugin
• Chapter 3, Photon Server – Star Collector, requires the Photon Server client and
server SDKs
• Chapter 4, Player.IO – Bot Wars, requires the Player.IO developer package
• Chapter 5, PubNub – The Global Chatbox, requires a third-party JSON parser
Instructions to download the required materials are covered at the beginning of each chapter
Who this book is for
This book is for developers who want to get started writing multiplayer games with the Unity game engine Readers are expected to have a working knowledge of C# Knowledge of the Unity IDE is helpful, but not strictly required
Conventions
In this book, you will find a number of styles of text that distinguish between
different kinds of information Here are some examples of these styles, and an explanation of their meaning
Code words in text are shown as follows: "Navigate to the Release folder and run the EXE."
Trang 15A block of code is set as follows:
public class ExampleUnityNetworkSerializePosition : MonoBehaviour {
public void OnSerializeNetworkView( BitStream stream,
// send the object's position
Vector3 position = transform.position;
stream.Serialize( ref position );
}
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
// the maximum score a player can reach
public int ScoreLimit = 10;
// the display test for player 1's score
public TextMesh Player1ScoreDisplay;
// the display text for player 2's score
public TextMesh Player2ScoreDisplay;
// Player 1's score
private int p1Score = 0;
New terms and important words are shown in bold Words that you see on the
screen, in menus, or dialog boxes for example, appear in the text like this: "clicking
the Next button moves you to the next screen".
Warnings or important notes appear in a box like this
Tips and tricks appear like this
Trang 16to develop titles that you really get the most out of.
To send us general feedback, simply send an e-mail to feedback@packtpub.com, and mention the book title via the subject of your message
If there is a topic that you have expertise in and you are interested in either writing
or contributing to a book, see our author guide on www.packtpub.com/authors
Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase
Downloading the example code
You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com If you purchased this book
elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you
Errata
Although we have taken every care to ensure the accuracy of our content, mistakes
do happen If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you would report this to us By doing so, you can save other readers from frustration and help us improve subsequent versions of this book If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the errata submission form link,
and entering the details of your errata Once your errata are verified, your submission will be accepted and the errata will be uploaded on our website, or added to any list of existing errata, under the Errata section of that title Any existing errata can be viewed
by selecting your title from http://www.packtpub.com/support
Trang 17Piracy
Piracy of copyright material on the Internet is an ongoing problem across all media
At Packt, we take the protection of our copyright and licenses very seriously If you come across any illegal copies of our works, in any form, on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy
Please contact us at copyright@packtpub.com with a link to the suspected
Trang 18Unity Networking – The Pong Game
Multiplayer is everywhere It's a staple of AAA games and small-budget indie
offerings alike Multiplayer games tap into our most basic human desires Whether
it be teaming up with strangers to survive a zombie apocalypse, or showing off your skills in a round of "Capture the Flag" on your favorite map, no artificial intelligence
in the world comes close to the feeling of playing with a living, breathing, and
thinking human being
Unity3D has a sizable number of third-party networking middleware aimed at
developing multiplayer games, and is arguably one of the easiest platforms to
prototype multiplayer games
The first networking system most people encounter in Unity is the built-in Unity
Networking API This API simplifies a great many tasks in writing networked code
by providing a framework for networked objects rather than just sending messages This works by providing a NetworkView component, which can serialize object state and call functions across the network
Additionally, Unity provides a Master server, which essentially lets players
search among all public servers to find a game to join, and can also help players in connecting to each other from behind private networks
In this chapter, we will cover:
• Introducing multiplayer
• Introducing UDP communication
• Setting up your own Master server for testing
• What a NetworkView is
Trang 19Unity Networking – The Pong Game
• Serializing object state
• Calling RPCs
• Starting servers and connecting to them
• Using the Master server API to register servers and browse available hosts
• Setting up a dedicated server model
• Loading networked levels
• Creating a Pong clone using Unity networking
Introducing multiplayer games
Before we get started on the details of communication over the Internet, what exactly does multiplayer entail in a game?
As far as most players are concerned, in a multiplayer game they are sharing the same experience with other players It looks and feels like they are playing the same game In reality, they aren't Each player is playing a separate game, each with its own game state Trying to ensure that all players are playing the exact same game
is prohibitively expensive Instead, games attempt to synchronize just enough information to give the illusion of a shared experience
Games are almost ubiquitously built around a client-server architecture, where each client connects to a single server The server is the main hub of the game, ideally the machine for processing the game state, although at the very least it can serve as a simple "middleman" for messages between clients Each client represents an instance
of the game running on a computer In some cases the server might also have a client, for instance some games allow you to host a game without starting up an external server program
While an MMO (Massively Multiplayer Online) might directly connect to one
of these servers, many games do not have prior knowledge of the server IPs For example, FPS games often let players host their own servers In order to show the user a list of servers they can connect to, games usually employ another server, known as the "Master Server" or alternatively the "Lobby server" This server's sole purpose is to keep track of game servers which are currently running, and report
a list of these to clients Game servers connect to the Master server in order to
announce their presence publicly, and game clients query the Master server to get an updated list of game servers currently running
Trang 20Chapter 1
[ 9 ]
Alternatively, this Master server sometimes does not keep track of servers at all Sometimes games employ "matchmaking", where players connect to the Lobby server and list their criteria for a game The server places this player in a "bucket" based on their criteria, and whenever a bucket is full enough to start a game, a host is chosen from these players and that client starts up a server in the background, which the other players connect to This way, the player does not have to browse servers manually and can instead simply tell the game what they want to play
Introducing UDP communication
The built-in Unity networking is built upon RakNet RakNet uses UDP
communication for efficiency
UDP (User Datagram Protocols) is a simple way to send messages to another
computer These messages are largely unchecked, beyond a simple checksum to ensure that the message has not been corrupted Because of this, messages are not guaranteed to arrive, nor are they guaranteed to only arrive once (occasionally a single message can be delivered twice or more), or even in any particular order TCP,
on the other hand, guarantees each message to be received just once, and in the exact order they were sent, although this can result in increased latency (messages must
be resent several times if they fail to reach the target, and messages must be buffered when received, in order to be processed in the exact order they were sent)
To solve this, a reliability layer must be built on top of UDP This is known as rUDP (reliable UDP) Messages can be sent unreliably (they may not arrive, or may arrive
more than once), or reliably (they are guaranteed to arrive, only once per message, and in the correct order) If a reliable message was not received or was corrupt, the original sender has to resend the message Additionally, messages will be stored rather than immediately processed if they are not in order For example, if you receive messages 1, 2, and 4, your program will not be able to handle those messages until message 3 arrives
Allowing unreliable or reliable switching on a per-message basis affords better overall performance Messages, such as player position, are better suited to
unreliable messages (if one fails to arrive, another one will arrive soon anyway), whereas damage messages must be reliable (you never want to accidentally drop a damage message, and having them arrive in the same order they were sent reduces race conditions)
In Unity, you can serialize the state of an object (for example, you might serialize the position and health of a unit) either reliably or unreliably (unreliable is usually preferred) All other messages are sent reliably
Trang 21Unity Networking – The Pong Game
Setting up the Master Server
Although Unity provide their own default Master Server and Facilitator (which is connected automatically if you do not specify your own), it is not recommended to use this for production We'll be using our own Master Server, so you know how to connect to one you've hosted yourself
Firstly, go to the following page:
http://unity3d.com/master-server/
We're going to download two of the listed server components: the Master Server and the Facilitator as shown in the following screenshot:
The servers are provided in full source, zipped If you are on Windows using Visual
Studio Express, open up the Visual Studio sln solution and compile in the Release
mode Navigate to the Release folder and run the EXE (MasterServer.exe or Facilitator.exe) If you are on a Mac, you can either use the included XCode project, or simply run the Makefile (the Makefile works under both Linux and
Trang 22Chapter 1
[ 11 ]
The Master Server, as previously mentioned, enables our game to show a server lobby to players The Facilitator is used to help clients connect to each other by
performing an operation known as NAT punch-through NAT is used when
multiple computers are part of the same network, and all use the same public IP address NAT will essentially translate public and private IPs, but in order for one machine to connect to another, NAT punch-through is necessary You can read more about it here:
http://www.raknet.net/raknet/manual/natpunchthrough.html
The default port for the Master Server is 23466, and for the Facilitator is 50005 You'll need these later in order to configure Unity to connect to the local Master Server and Facilitator instead of the default Unity-hosted servers
Now that we've set up our own servers, let's take a look at the Unity Networking API itself
NetworkViews and state serialization
In Unity, game objects that need to be networked have a NetworkView component
The NetworkView component handles communication over the network, and even helps make networked state serialization easier It can automatically serialize the state of a Transform, Rigidbody, or Animation component, or in one of your own scripts you can write a custom serialization function
When attached to a game object, NetworkView will generate a NetworkViewID
for NetworkView This ID serves to uniquely identify a NetworkView across the network An object can be saved as part of a scene with NetworkView attached (this can be used for game managers, chat boxes, and so on), or it can be saved in the project as a prefab and spawned later via Network.Instantiate (this is used to generate player objects, bullets, and so on) Network.Instantiate is the multiplayer equivalent to GameObject.Instantiate—it sends a message over the network to other clients so that all clients spawn the object It also assigns a network ID to the object, which is used to identify the object across multiple clients (the same object will have the same network ID on every client)
A prefab is a template for a game object (such as the player object)
You can use the Instantiate methods to create a copy of the template in the scene
Trang 23Unity Networking – The Pong Game
Spawned network game objects can also be destroyed via Network.Destroy It is the multiplayer counterpart of GameObject.Destroy It sends a message to all clients so that they all destroy the object It also deletes any RPC messages associated with that object
NetworkView has a single component that it will serialize This can be a
Transform, a Rigidbody, an Animation, or one of your own components that has
an OnSerializeNetworkView function Serialized values can either be sent with
the ReliableDeltaCompressed option, where values are always sent reliably and
compressed to include only changes since the last update, or they can be sent with
the Unreliable option, where values are not sent reliably and always include the
full values (not the change since the last update, since that would be impossible to predict over UDP) Each method has its own advantages and disadvantages If data
is constantly changing, such as player position in a first person shooter, in general Unreliable is preferred to reduce latency If data does not often change, use the ReliableDeltaCompressed option to reduce bandwidth (as only changes will
be serialized)
NetworkView can also call methods across the network via Remote Procedure Calls (RPC) RPCs are always completely reliable in Unity Networking, although some
networking libraries allow you to send unreliable RPCs, such as uLink or TNet
Writing a custom state serializer
While initially a game might simply serialize Transform or Rigidbody for testing, eventually it is often necessary to write a custom serialization function This is a surprisingly easy task
Downloading the example code
You can download the example code files for all Packt books you have
purchased from your account at http://www.packtpub.com If you
purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you
Here is a script that sends an object's position over the network:
Trang 24// send the object's position
Vector3 position = transform.position;
stream.Serialize( ref position );
}
// we are currently reading information from the network
else
{
// read the first vector3 and store it in 'position'
Vector3 position = Vector3.zero;
stream.Serialize( ref position );
Using RPCs
RPCs are useful for single, self-contained messages that need to be sent, such as a character firing a gun, or a player saying something in chat
In Unity, RPCs are methods marked with the [RPC] attribute This can be called
by name via networkView.RPC( "methodName", … ) For example, the following script prints to the console on all machines when the space key is pressed
Trang 25Unity Networking – The Pong Game
ours
if( !networkView.isMine )
return;
// if space key is pressed, call RPC for everybody
if( Input.GetKeyDown( KeyCode.Space ) )
networkView.RPC( "testRPC", RPCMode.All );
}
[RPC]
void testRPC( NetworkMessageInfo info )
{
// log the IP address of the machine that called this RPC
Debug.Log( "Test RPC called from " + info.sender.ipAddress ); }
}
Also note the use of NetworkView.isMine to determine ownership of an object All scripts will run 100 percent of the time regardless of whether your machine owns the object or not, so you have to be careful to avoid letting some logic run on remote machines; for example, player input code should only run on the machine that owns the object
RPCs can either be sent to a number of players at once, or to a specific player
You can either pass an RPCMode to specify which group of players to receive the message, or a specific NetworkPlayer to send the message to You can also specify any number of parameters to be passed to the RPC method
RPCMode includes the following entries:
• All (the RPC is called for everyone)
• AllBuffered (the RPC is called for everyone, and then buffered for when new
players connect, until the object is destroyed)
• Others (the RPC is called for everyone except the sender)
• OthersBuffered (the RPC is called for everyone except the sender, and then
buffered for when new players connect, until the object is destroyed)
• Server (the RPC is sent to the host machine)
Note that, with the exception of RPCMode.All and RPCMode
AllBuffered, a client cannot send an RPC to itself
Trang 27Unity Networking – The Pong Game
You can also optionally enable an incoming password (useful for private games)
by setting Network.incomingPassword to a password string of the player's choice, and initializing a general-purpose security layer by calling Network.InitializeSecurity() Both of these should be set up before actually initializing the server
Note that incoming connections does not mean maximum player count, since it does not include the host (for example, if you allow
8 players to connect, it's possible for 9 players to play in the same room—8 clients plus the host)
Connecting to a server
To connect to a server you know the IP address of, you can call Network.Connect.The following script allows the player to enter an IP, a port, and an optional password and attempts to connect to the server:
private string port = "";
private string password = "";
void OnGUI()
{
GUILayout.Label( "IP Address" );
ip = GUILayout.TextField( ip, GUILayout.Width( 200f ) );
Trang 29Unity Networking – The Pong Game
Connecting to the Master Server
While we could just allow the player to enter IP addresses to connect to servers (and many games do, such as Minecraft), it's much more convenient to allow the player to browse a list of public servers This is what the Master Server is for
Now that you can start up a server and connect to it, let's take a look at how to connect to the Master Server you downloaded earlier First, make sure both the Master Server and Facilitator are running I will assume you are running them on your local machine (IP is 127.0.0.1), but of course you can run these on a different computer and use that machine's IP address Keep in mind, if you want the Master Server publicly accessible, it must be installed on a machine with a public IP address (it cannot be in a private network)
Let's configure Unity to use our Master Server rather than the Unity-hosted test server The following script configures the Master Server and Facilitator to connect to
a given IP (by default 127.0.0.1):
Trang 30Immediately after making a call to Network.InitializeServer, make another call
to MasterServer.RegisterHost This call connects to the Master Server and tells it
to display our server in the public game list
The RegisterHost function takes three parameters, all strings: gameTypeName, gameName, and comment The game type name is used to separate different game listings from each other For example, if two games use the same Master Server, they would both supply different game type names in order to avoid getting listings for the other game The game name is the name of the host server, for example
"John's server" The comment is a general purpose data string, essentially anything can be stored here For example you could store data about the server (such as map rotation, available modes, and so on) and display these to the user while they browse the lobby
Because RegisterHost is a separate call from InitializeServer, you can simply omit the call to RegisterHost to implement private or LAN-style servers
You can call RegisterHost more than once while a server is running
to update the information stored on the Master Server For example,
if the server changes to a new level, you might call RegisterHost again to update the lobby
Browsing available servers
To browse the available servers, call MasterServer.RequestHostList This takes one single parameter: the game type name (this is the same game type name you passed to RegisterHost)
This does not return anything, instead the result will be asynchronously
downloaded, and the last known list of servers can be accessed via MasterServer.PollHostList Additionally, to ensure you aren't using old data, you can call
MasterServer.ClearHostList For example, if the user hits the Refresh button in the lobby you might clear the host list and then request a new list from the
Master Server
Trang 31Unity Networking – The Pong Game
The following script shows a lobby for users to browse available servers and connect
// are we currently trying to download a host list?
private bool loading = false;
// the current position within the scrollview
private Vector2 scrollPos = Vector2.zero;
HostData[] hosts = MasterServer.PollHostList();
for( int i = 0; i < hosts.Length; i++ )
Trang 32void OnMasterServerEvent( MasterServerEvent msevent )
The preceding code will list available servers registered to the Master Server
Clicking one of the buttons will call the Network.Connect function and connect
to the corresponding server, and clicking on Refresh will display a Loading
message while results are fetched from the Master Server There are a number of improvements and other tweaks that can be made to this code, left as an exercise for the reader:
• Refresh the host list every few seconds This should be done transparently, without displaying a "Loading" message
• Allow the user to add servers to a "favorites" list (possibly saved as CSV to PlayerPrefs), if your game allows players to run dedicated servers
Trang 33Unity Networking – The Pong Game
• If the user attempts to connect to a password-protected game (HostData.passwordProtected is true), display a password entry field
• Save game information such as map, mode, and so on in the Comments field
when registering a server, and allow the user to filter server results
Setting up a dedicated server model
Many games allow players to host their own dedicated servers, as separate
applications from the game client Some games even allow players to modify the behavior of the server through scripting languages, allowing player-run servers to employ novel behaviors not originally designed into the game
Let's see how we can set up a similar system in Unity I will not be covering
modding, although readers can look up Lua scripting in Unity—there are a number
of resources on the topic
Servers in Unity
Most games have a specialized "server" build, which contains much the same code as the client, designed to run as a dedicated server This allows the server to process the same logic as the client
Unity, however, does not directly support this concept out of the box Unity Pro does allow builds to be run in "headless mode", which runs the game without initializing any graphics, resources, but the server runs the exact same code as the client The game must be designed to operate in both server and client mode
To do this, we'll take advantage of a compiler feature known as "conditional
compilation" This allows us to wrap code in special tags which allows us to strip out entire sections of code when compiling This way, our server-only code will only be included in server builds, and our client-only code will only be included in client builds
Compiler directives
The first thing we will do, is figure out how the application knows whether it is a client or a server We will use a compiler directive to do this
If you are using Unity 4, you can go to Edit | Project Settings | Player and under
Other Settings is a section that allows you to define these.
Trang 34Chapter 1
[ 23 ]
However, for any version prior to Unity 4, you'll have to define these yourself To do
this, create a new text file in the Assets folder and name it smcs.rsp Open Notepad and type:
You might consider writing an editor script which replaces the contents of this
file (when compiling for the client, it would replace SERVER with CLIENT, and
vice versa) It is important to note that changes to this file will not automatically recompile, when changing the file you should save one of your scripts Your editor script might do this automatically, for example it could call AssetDatabase
Refresh( ImportAssetOptions.ForceUpdate )
Now that we can detect whether the application was built as a server or a client, we'll need some way for the server to act as autonomously as possible The server should have a configuration file which allows the user to set, for example, network settings before the server runs This book will not cover how to load the configuration file (XML or JSON are recommended), but once these are loaded the server should immediately initialize and register itself with the Master Server using the data in the configuration file (for example, server name, maximum connections, listen port, password, and so on)
Setting up a server console without Pro
Usually, a game server is a console application This is nearly possible in Unity if you have purchased a Pro license, by appending the -batchmode argument to the executable (actually, Unity does not create a console window, instead the game simply runs in the background) If you do have Pro, feel free to skip this section However, if you own a free license, you'll need to get a bit creative
We want the server to use as few resources as possible We can create a script that turns off rendering of the scene when running in server mode This won't completely disable the rendering system (as running in command line would), but it does
significantly reduce the GPU load of the server
using UnityEngine;
using System.Collections;
public class DisableServerCamera : MonoBehavior
Trang 35Unity Networking – The Pong Game
public string message;
public LogType type;
}
public class CustomLog : MonoBehavior
{
// how many past log messages to store
public int MaxHistory = 50;
// a list of stored log messages
private List<LogMessage> messages = new List<LogMessage>();
// the position within the scroll view
private Vector2 scrollPos = Vector2.zero;
void OnEnable()
{
// register a custom log handler
Application.RegisterLogCallback( HandleLog );
Trang 36//draw each debug log – switch colors based on log type
for( int i = 0; i < messages.Count; i++ )
{
Color color = Color.white;
if( messages[i].type == LogType.Warning )
// add the message, remove entries if there's too many
LogMessage msg = new LogMessage();
Trang 37Unity Networking – The Pong Game
// scroll to the newest message by setting to a huge amount
// will automatically be clamped
• As previously mentioned, the server starts up automatically with a
configuration loaded from the user-editable files (unlike the client)
• The server does not spawn any player objects of its own, unlike the client
• The server does not have any UIs or menus to display to the user beyond the log dump Beyond starting up the server and shutting it down, there is zero interaction with the server application
Loading networked levels
There are a few tricks to loading networked levels in the Unity game engine If you just use Application.LoadLevel, you'll encounter a number of issues; specifically you may find that a client connecting to the game won't see any objects that were instantiated via Network.Instantiate The reason for this is because the level loading process doesn't happen instantly—it actually takes two frames to complete This occurs after the list of networked objects was received, so the load process will delete them
Note that Application.LoadLevel is purely client side Unity imposes no
limitations on which level a client or server loads in a networked game In fact, it's entirely possible that you might have different levels within a networked session, and this is what Network.SetLevelPrefix is for Each of these levels is assigned some kind of "ID" that uniquely identifies the level Before loading the level you would use Network.SetLevelPrefix This essentially separates players into
channels, so all players with level prefix 0 are separate from players with level prefix 1, for example
Trang 38Chapter 1
[ 27 ]
Note that if your game needs all clients to load the same level, you'll have to ensure this yourself If a client has a different level loaded than the host, without setting the level prefix to something different than the host, the client might see some odd situations, such as players floating or sunk into the ground (a player could be standing on a bridge in one level, and a different level at the same position might have a building; so the player would appear to be clipped into the building)
The correct way to load levels in a networked game, is to first disable the network queue, load the level, wait two frames, and then re-enable the network queue This means any incoming messages will not be processed, and will instead be buffered until the new level has completely finished loading
Let's write a simple network level loader that will handle all of these for us
It's designed as a singleton so we don't need one present in the scene (one will automatically be created):
using UnityEngine;
using System.Collections;
public class NetworkLevelLoader : MonoBehavior
{
// implements singleton-style behavior
public static NetworkLevelLoader Instance
{
get
{
// no instance yet? Create a new one
if( instance == null )
private static NetworkLevelLoader instance;
public void LoadLevel( string levelName, int prefix = 0 )
{
StopAllCoroutines();
Trang 39Unity Networking – The Pong Game
StartCoroutine( doLoadLevel( levelName, prefix ) );
yield return null;
yield return null;
Network.isMessageQueueRunning = true;
Network.SetSendingEnabled( 0, true );
}
}
You can now replace any calls to Application.LoadLevel with
NetworkLevelLoader.Instance.LoadLevel For example, the server might call an RPC which loads the level via the helper class we just wrote, as a buffered RPC so that all clients connecting will automatically load the level
If your server needs to change level during the connection, for example,
in many FPS games players can vote on a new map at the end of a
round, things get a bit more complicated The server should first delete all networked objects belonging to players, remove RPCs from all
players (via Network.RemoveRPCs), and then call the load-level RPC
Creating a multiplayer Pong game
Now that we've covered the basics of using Unity Networking, we're going to apply them to creating a multiplayer Pong clone
The game will play pretty much as standard Pong Players can choose their name, and then view a list of open servers (full rooms will not be shown) Players can also host their own game
Trang 40Chapter 1
[ 29 ]
Once in a game, players bounce a ball back and forth until it hits the opponent's side Players get one point for this, and the ball will reset and continue bouncing When a player hits 10 points, the winner is called, the scores are reset, and the game continues While in a match with no other players, the server will inform the user
to wait If a player leaves, the match is reset (if the host leaves, the other player is automatically disconnected)
Preparing the Field
First, create a cube (by navigating to GameObject | Create Other | Cube) and scale
it to 1 x 1 x 4 Name it Paddle and set the Tag to Player Check the Is Trigger box on
the collider
Our ball will detect when it hits the trigger zone on the player paddle, and reverse direction We use triggers because we don't necessarily want to simulate the ball realistically with the Unity physics engine (we get far less control over the ball's physics, and it may not behave exactly as we would like)