-
-
Notifications
You must be signed in to change notification settings - Fork 305
Network Messages
Directory | Previous | Next |
---|---|---|
Directory | Getting Started With Alloy | Network Message Interpreters |
Network messages are the very core of Forge Networking in this latest revision.
To create a message and an interpreter automatically use the right click context menu Create -> Forge Networking -> Network Message Script
.
After you select the network message script option you will be presented with the following dialog window.
Message name: This will be the C# class name for your script. The word Message
is automatically appended to the end of the message name, so there is no need for you to type that as part of the name.
Interpret on server: If this checkbox is enabled, then this message is allowed to be interpreted on the server. This means if a client sends this message to the server, it will execute its behavior. If you do not check this box, then the server will ignore this message if it is received.
Interpret on client: If this checkbox is enabled, then this message is allowed to be interpreted on the client. This means if a server sends this message to the client, it will execute its behavior. If you do not check this box, then the client will ignore this message if it is received.
Singleton Interpreter: This is the default and probably isn't something you would want to turn off unless you are an advanced developer in need of creating new instances of this interpreter for the message to be read by. By turning this on, you will still be able to new up the class (for unit tests and any other reasons), so don't worry.
Note about singletons: I am by no means a fan of singletons, the only singletons that make any sense are ones that contain no state and are supplied arguments to work with, basically turning them into static functions/classes.
The message is mainly a data object, that is to say it is a class that's primary role is to house some properties that describe the message. You see that the message is decorated with some information like EngineMessageContract
but we'll cover that more in detail in the advanced info section of this page. Below is an example of a message which was created using the name Chat and was selected to be interpreted both on the client. Note that I've filled out some dummy data for this sample. Also note that the value 6 is chosen at random for EngineMessageContract
in this sample.
[EngineMessageContract(6, typeof(Chat))]
public class ChatMessage : ForgeMessage
{
public string Name { get; set; }
public string Text { get; set; }
public override IMessageInterpreter Interpreter => ChatInterpreter.Instance;
public override void Deserialize(BMSByte buffer)
{
Name = ForgeSerializer.Instance.Deserialize<string>(buffer);
Text = ForgeSerializer.Instance.Deserialize<string>(buffer);
}
public override void Serialize(BMSByte buffer)
{
ForgeSerializer.Instance.Serialize(Name, buffer);
ForgeSerializer.Instance.Serialize(Text, buffer);
}
}
Let's start by going over the properties. We have 2 properties Name and Text (both happen to be strings in this case, but you can use any data type you wish). These fields do not need to be filled out when you create the message, but need to be filled out before you send the message across the network. This is the data that you are wishing to send, this could be player position (Vector3), some sort of identifier (int), etc.
Next you will notice the Interpreter for the message, this is the class that will be handling this message when it is received on the network. We will go into more details on what the interpreter is and does in the Network Message Interpreters documentation page.
Now on to the Deserialize and the Serialize functions respectively. It is important that you take note of the order that you serialize and deserialize your message data. These functions are the place where you can write custom code to compress your data (say you want to send less data over the wire) or you can send the data raw. You could even choose not to send specific fields of the message and instead use that field for other purposes to describe how to compress the message for example. Again, the order does matter. Make sure if you Serialize
first the Name field and then the Text field, that you Deserialize
them in that exact same order Name then Text just as you can see in the sample.
Lastly you see the ForgeSerializer
come into play here for serialization and deserialization. We will go more into details about the ForgeSerializer
in the Serialization Strategy documentation page. For now, just know that it is responsible for knowing how to take a specific data type and write it to bytes and also how to take a series of bytes and convert them back into a specific data type.
There is a fancy thing called a NetworkMediator
that takes on the responsibility of sending your messages. The easiest way to get this mediator from anywhere is to get the reference to the ForgeEngineFacade
. The engine facade is a way of interfacing with the larger Forge code from within your engine code (thus "Engine" in it's name). You typically can find a reference to this object by doing GameObject.FindObjectOfType<ForgeEngineFacade>();
from within your code. With a reference to this object you can send your message.
ChatMessage m = new ChatMessage
{
Name = "Forge",
Text = "Hello World!"
};
IEngineFacade engine = GameObject.FindObjectOfType<ForgeEngineFacade>();
ISocket mySocket = engine.NetworkMediator.SocketFacade.ManagedSocket;
engine.NetworkMediator.SendReliableMessage(m, mySocket.EndPoint);
Note: Please also review Message Pools
What if 2 of my messages have the same message code (6 in our sample)?
- In Unity, go to
Window -> Forge -> Networking Editor
- Click on Message Checker
- This window will tell you if you have any message conflicts
- Look at the top of the window, it will tell you the next available message code that is free
- Go to one of the conflicting message codes and change the number manually to the number you see in the window
You may have come to this section of the documentation to learn about what the EngineMessageContract
is and how it works. Before continuing I would like to point out there are many different kinds of attributes that describe message contracts. You can view the code that defines all there attributes here.
The message contract attribute is responsible for separating out the messages by a given id (6 in our sample above). When the message comes across the network there has to be a way of identifying what type of message it is, this code is responsible for looking up what type to create based on the identifier.
The reason there are many attributes is because we want to make sure that the underlying Forge Networking code has the ability to create some pre-made messages for the system to operate. So that we don't overwrite developers' identifiers, we have made it so that you, the developer, will use EngineMessageContractAttribute
to describe your messages. This basically is the negative number space, while Forge will occupy the positive number space (so you get 1 extra message than the Forge number space).
If this is all confusing, don't worry, you can come back to this at a later time, there is no need for you to worry about understanding this portion right now.
The template system in Forge Alloy is much less a system and much more a file selection and modifying it's contents. The file templates can be located in the Assets/ForgeNetworking/Editor/Resources/ForgeNetworking/Templates
folder. As it relates to Messages, you'll see a MessageTemplate.txt file and a MessageTemplateSingleton.txt. Based on if you select for the interpreter to be a singleton or not will select which of the two templates to use.
Directory | Previous | Next |
---|---|---|
Directory | Getting Started With Alloy | Network Message Interpreters |
Getting Started
Network Contract Wizard (NCW)
Remote Procedure Calls (RPCs)
Unity Integration
Basic Network Samples
Scene Navigation
Master Server
Netcoding Design Patterns
Troubleshooting
Miscellaneous
-
Connection Cycle Events
-
Rewinding
-
Network Logging
-
Working with Multiple Sockets
-
Modify Master and Standalone servers
-
NAT Hole Punching
-
UDP LAN Discovery
-
Offline Mode
-
Ping Pong
-
Lobby System
-
Upgrading Forge Remastered to Develop branch or different version
-
Forge Networking Classic to Remastered Migration Guide
-
Script to easily use Forge Networking from sources
-
Run Two Unity Instances with Shared Assets for Easiest Dedicated Client Workflow