-
Notifications
You must be signed in to change notification settings - Fork 0
Networking
Each game needs one instance of STR dedicated to controlling the game. It not does have to be on a separate computer, but it is a standalone program. The server has the definitive definition of the state on the game, all user input goes through the server and all in-game changes are done on the server. The server updates each of the clients as to the current state of the game.
STR has one MasterServer (and a number of backups), which is on an Amazon EC2 cloud computer. This stores a list of all the servers currently running STR in the world. Every client connects to this to when it enters the lobby area. The MasterServer also deals with issues with a router being configured to forward ports to the server. By creating an outgoing connecting to the MasterServer, the server can then use that to receive clients.
The client is the mode of STR which a user plays in. Effectively, all it does is pass user input on to the server, and render the current state of the game from the server. More advanced features can be implemented, such as movement prediction, which will be discussed later.
Remember that, although the server and client are distinct modes of the game, they almost always use the scripts. To make them operate differently, please uses the Network.isServer and Network.isClient variables
The class NetworkView is very important while networking. Objects use this to communicate and to differentiate themselves. At compile time each one is assigned a unique number (in the form of a NetworkViewID), which can be useful to describe an object. Problems can occur when running two different builds because objects have different NetworkViewIDs.
An RPC is a method to call a function on a different machine. Although it hardly mentions it anywhere, remember that you can only call a function inside the same script you are in. This was only a problem for us because the Server and Client networking scripts are different. This was fixed with a Bridge class which simply passes the RPC on - extend this class to do the same for you if you need it.
Any class which will be sending (and so always receiving) RPC calls must be attached to a GameObject with a NetworkView component. The function in the script attached to the GameObject with the same NetworkViewID will called one an RPC is received. The function to be called remotely should have [RPC] on the line before its definition.
More infomation can be found here.
This allows variables to be synchronised
Still want the paradigm of the server having the definitive state with all changes happening on the server. But we can reduce the communications by having the clients controlling some elements that we know their movement for the future. You should try to maximise the predictability of movement or ability of describe the movement in the near future.
For example, the AI can be designed so that it is stationary for most of the time, with movements every now and again. This can be implemented by sending an RPC every time the enemy wants to move describing the movement. This way the script on the client side can perform the movement without need of communication. Since the bullets have very predictable movement (constant velocity) their target and speed can be send via RPC.
##Implementation
Make sure the script you want to send the RPC call is attached to a GameObject which also have a networkView component attached to it. The function to be called by the RPC call should have [RPC] before it:
[RPC]
void receiveRPC( int value) {
Debug.Log("Received: " + value);
}
To send the RPC, use the RPC function in NetworkView that is attached.
networkView.RPC("receiveRPC", RPCMode.All, id, 5); You can choose the recipient of the RPC call with the following options:
- Server: Sends to the server only.
- Others: Sends to everyone except the sender.
- OthersBuffered: Sends to everyone except the sender and adds to the buffer.
- All: Sends to everyone.
- AllBuffered: Sends to everyone and adds to the buffer.
When an object is going to have a constant movement, there is no need for the state synchronisation, it should be implemented in the following way:
Instantiate the object on the network:
Transform bullet = (Transform)Network.Instantiate(prefab, new Vector3(0,0,0), 200);
This will instantiate the object on all clients subscribed to group 200. In the prefab, make sure that a networkView is attached, but that it has state synchronisation off. Make an RPC receiving function with all the arguments needed to describe the objects moment. This will probably be direction and magnatude of force to apply.
[RPC]
void setupBullet(Vector3 direction, Vector3 force) {
Send all this information to the clients using this function
networkView.RPC("setupWeapon", RPCMode.All, direction, force);
There can be issues with the server and clients having slightly different versions of the game, so it has better for the object on the client to have no iteration with anything, and when interactions occur, to have them RPCed to the client. Consider programmatically turning the colder off on the client.