This will be a short usage guide on LLAPI and using the MessageBase for sendign data. Assuming that you already have prior knowledge on how to start a connection and send data. If you don’t then please refer to unity manual.
privateboolReceiveEvents() { byte error; int incConnectionId, incChannelId, incReceivedSize, incHostId;
var networkEvent = NetworkTransport.ReceiveFromHost(hostId, out incConnectionId, out incChannelId, buffer, (ushort)buffer.Length, out incReceivedSize, out error);
if (error != 0) { Debug.LogError("Error: " + error); // you should handle errors here for example // player timing out is considered an error code 6 if(error == 6) { OnPlayerDisconnected(incConnectionId); } returnfalse; }
switch (networkEvent) { case NetworkEventType.Nothing: returnfalse; case NetworkEventType.ConnectEvent: OnPlayerConnected(incConnectionId); break; case NetworkEventType.DataEvent: reader = new NetworkReader(buffer); ushort size = reader.ReadUInt16(); short type = reader.ReadInt16(); OnDataReceived(incConnectionId, reader, size, type); break; case NetworkEventType.DisconnectEvent: OnPlayerDisconnected(incConnectionId); break; case NetworkEventType.BroadcastEvent: // TODO break; default: thrownew ArgumentOutOfRangeException(); } returntrue; }
Setting hostId to -1 so we could know when we are not using the transport. You could use 0 as well because first connection id is 1. After this you want to receive events from transport layer. We put all of them in a switch. I left out BroadcastEvent as this is for searching for active hosts on LAN. We place virtual methods to get called on connect/disconnect and to shutdown transport when the manager is destroyed.
NetworkTransport.AddHost – will open port for incoming and outgoing communications NetworkTransport.Connect – connects to a remote open host
You cannot reuse the same port on different connections on the same machine. Once it is occupied you have to use a different one. When starting local client and server you need to open one port for server communications and then a different one for client communication but direct that to the servers port.
A good starting point on organizing your data sent is extending MessageBase. It as good practice to name all messages with a prefix of CS or SC if they are to be used only one way. In my own project I would treat these messages when sent from opposite side than expected as a request for info. If SC is received on server then we can send that message to client.
We define the message id as a short and then extend MessageBase. You define some variable you want to send and Serialize/Deserialize methods. For Serialize you should always StartMessage and FinishMessage. The following will add message id and size to the NetworkWriter. As for Deserialize it is enough to just read all input.
Let’s now reuse our Manager and set up connection between client and server:
protectedoverridevoidOnDataReceived(int id, NetworkReader reader, ushort size, short type) { switch (type) { case MessageTypes.CSHello: CSHello hello = new CSHello(); hello.Deserialize(reader); OnHello(id, hello); break; case MessageTypes.SCGoodbye: break; } }
publicvoidOnHello(int id, CSHello hello) { Debug.Log("Received Hello message from client saying: " + hello.greeting); SCGoodbye bye = new SCGoodbye("It is all about Transport layer!!!"); SendNetworkMessage(id, reliable, bye); } } }
When server receives a message with id of CSHello it will then deserialize it and send a new SCGoodbye to client.
using System.Collections; using System.Collections.Generic; using UnityEngine; using Networking; using UnityEngine.Networking;
namespaceMyNetworking { publicclassClient : Networking.Manager { protectedoverridevoidOnDataReceived(int id, NetworkReader reader, ushort size, short type) { switch (type) { case MessageTypes.SCGoodbye: SCGoodbye bye = new SCGoodbye(); bye.Deserialize(reader); OnGoodbye(bye); break; } }
publicvoidOnGoodbye(SCGoodbye bye) { Debug.Log("Received from server: " + bye.greeting); }
protectedoverridevoidOnPlayerConnected(int id) { Debug.Log("Client: successfully connected..."); CSHello hello = new CSHello(); hello.greeting = "I love UNET HLAPI!"; SendNetworkMessage(id, reliable, hello); } } }
When we establish connection to server it sends a CSHello in OnPlayerConnected and after receiving SCGoodbye from server we will log it to console.
Test it out!
In your scene create new gameobject and attach Server and Client components. Set up two UI Buttons and to one add StartServer() from Server component and from Client StartClient. In the string field write a port number (both should be matching).
Now this is by no means a very good implementation. But for anyone starting out it should do good enough as a starting point on how to organize the code and use MessageBase.