Skip to content

Commit 335b292

Browse files
committed
Added initial readme.md
1 parent 2bf32ee commit 335b292

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

Readme.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Protobuffers over network for Unity3D
2+
This project lets you quickly and easily send protobuffer objects over the
3+
network between 2 apps. The protobuffers will get automatically compressed if
4+
they are larger than 1mb in order to save space when sending them through the
5+
network.
6+
7+
# How it works
8+
The way the project works is with a messaging system. Messages get sent
9+
through sockets. On one side one application has a listening socket and on
10+
the other side the application sends messages to it.
11+
12+
*Messages* are the basic way how protobuffers are sent, a message always
13+
contains a Protobuffer and a *Type* that identifies the protobuffer object you
14+
are sending.
15+
16+
# Project Structure
17+
In the unity project, There are 2 scenes. **SimpleClient** and
18+
**SimpleServer**.
19+
20+
All the information you need to run the project is contained in these 2
21+
scenes, specifically in 2 files called *ClientTest.cs* (for sending messages)
22+
and *ServerTest.cs* for receiving messages.
23+
24+
## SimpleClient scene.
25+
*SimpleClient* is an empty scene that contains a *ClientTest.cs* Behaviour
26+
added to the main camera.
27+
28+
This scene acts as a client and sends messages to the other application
29+
called *SimpleServer* which acts as the listening socket.
30+
31+
### ClientTest.cs
32+
In order to send a Protobuf object to another application, you need to open a
33+
socket and send a Protobuf object encapsulated in a Message object. convert it
34+
to an array of bytes and send it.
35+
36+
The *ClientTest.cs* class contains precissely that function already for you to
37+
send messages and its called:
38+
39+
*void SendMessage(Message m);*
40+
41+
In ClientTest.cs you will find the UI for setting up values for the
42+
SampleObject protobuf object and the address and port of the app you want to
43+
send the values to.
44+
45+
## SimpleServer Scene.
46+
*SimpleServer* is an empty scene that contains a *ServerTest.cs* Behaviour
47+
attached to the main camera.
48+
49+
This scene acts as a server that is continuously listening on a port for
50+
incoming messages from any client. It processes the messages, rebuilds them
51+
and print them.
52+
53+
### ServerTest.cs
54+
In order to receive a protobuf object, a *SocketProtobufListener* object
55+
needs to be created. This object receives an IP, a port where the socket
56+
is going to be listening for incoming messages and a *ConcurrentQueue* for
57+
*ProtobufMessages* that are stored in the Queue as they come.
58+
59+
The *ServerTest.cs* creates a SocketProtobufListener object, binds a socket
60+
automatically to the current IP used and on a separate thread a socket starts
61+
to listen for incoming messages, these messages are stored in the
62+
*messaQueue* declared in the class.
63+
64+
When a message gets added to the queue, in the Update function as soon as a
65+
message arrives, the protobuf message gets read and depending on the type it
66+
has, it gets casted and then printed in the UI with the
67+
*PrintSampleObjectFields(SampleObject s)* function.
68+
69+
70+
# How to add a Protobuf Object and transmit it over the network
71+
Here I will walk you through on how to send an object and receive it on the
72+
other end. This app doesnt check for errors in connections nor anything
73+
else. This is left for you, the reader.
74+
75+
First things first. We need to create a Protobuf object. I will not cover the
76+
specific syntax on how protobuffer objects work, for more reference just
77+
check it out [here](https://developers.google.com/protocol-buffers/docs/overview).
78+
79+
In order to compile our SampleObject you need to have **protoc** installed
80+
and compile the protobuffer for C#. After that you are pretty much done.
81+
82+
Our *SampleObject.proto* looks like this:
83+
84+
>package Protobuf;
85+
>
86+
>message SampleObject {
87+
> int32 type = 1;
88+
> string objectName = 2;
89+
> string sampleString = 3;
90+
> int32 sampleInt = 4;
91+
> float sampleFloat = 5;
92+
>}
93+
94+
It contains a *type* which is **necessary** for all your objects you want to
95+
transmit. 2 sample strings, a float and an integer.
96+
97+
After compiling the protocol buffer to C# we need to tell the system with a
98+
unique identifier the type of the object. This is added in *ProtobufMessagesTypes.cs*
99+
100+
>//ProtobufMessageTypes.cs
101+
>public static class ProtobufMessageTypes {
102+
> public const int SAMPLE_OBJECT = 1;//can have any value, just make sure is unique
103+
>}
104+
105+
Then, we create a function for creating this object message in
106+
*MessageCreator.cs*. Here we define a function that creates an object with
107+
the parameters and returns a message (See MessageCreator.cs for the
108+
implementation details).
109+
110+
>//MessageCreator.cs
111+
>public static Message CreateSampleObjectMessage(string objName, string sampleStr, int sampleInt, float sampleFloat)
112+
113+
In order to receive and undertand the message, we have to convert the message
114+
to a ProtobufMessage, this is done in *DeserializeByType(int type, MemoryStream memStream)*
115+
116+
>//MessageDeserializer.cs
117+
>private static ProtobufMessage DeserializeByType(int type, MemoryStream memStream) {
118+
> object protobuf = null;
119+
> switch (type) {
120+
> case ProtobufMessageTypes.SAMPLE_OBJECT:
121+
> protobuf = Protobuf.SampleObject.Parser.ParseFrom(memStream);
122+
> break;
123+
> default:
124+
> return null;
125+
> }
126+
> return new ProtobufMessage(protobuf, type);
127+
>}
128+
129+
Finally, in the *Update()* function in *ServerTest.cs* we can cast our
130+
ProtobufMessage.cs with the specific type to our object.
131+
132+
>// ServerTest.cs
133+
>void Update() {
134+
> if(messageQueue.Count > 0) {//when there's a protobuf message in the queue, we print it
135+
> ProtobufMessage pm;
136+
> messageQueue.TryDequeue(out pm);
137+
>
138+
> switch(pm.MessageType) {
139+
> case ProtobufMessageTypes.SAMPLE_OBJECT:
140+
> SampleObject sampleObject = (SampleObject) pm.Protobuf;
141+
> //Do something with our object
142+
> break;
143+
> }
144+
> }
145+
> }
146+
>}

0 commit comments

Comments
 (0)