F8 Network
June 27, 2025 · View on GitHub
Introduction (Simply press F8 to start game development without distractions)
Unity F8 Network Component
Multi-protocol Networking Solution for Client-Server Communication
- Multi-protocol Support:
- KCP Protocol: High-speed reliable UDP with congestion control
- TCP Protocol: Traditional reliable connection
- WebSocket: Web-compatible communication
- Dual-mode Operation:
- Full Client implementation
- Complete Server implementation
- Shared codebase for both endpoints
- Connection Management:
- Persistent long-lived connections
- Automatic reconnection
- Connection state monitoring
Plugin Installation (Requires Core Framework First)
Note! Built into → F8Framework Core: https://github.com/TippingGame/F8Framework.git
Method 1: Download files directly and import to Unity
Method 2: Unity → Menu Bar → Window → Package Manager → "+" → Add Package from git URL → Enter: https://github.com/TippingGame/F8Framework.git
Usage Guide
KCP/TCP Protocol Usage
- Client Implementation MultiNetworkClient.cs
/*----------------------------TCP/KCP Client Usage----------------------------*/
// Create TCP channel
TcpClientChannel tcpClientChannel = new TcpClientChannel("TEST_TCP_CLIENT");
// Create KCP channel
KcpClientChannel kcpClientChannel = new KcpClientChannel("TEST_KCP_CLIENT");
// Set callbacks
tcpClientChannel.OnConnected += TcpClient_OnConnected;
tcpClientChannel.OnDataReceived += TcpClient_OnDataReceived;
tcpClientChannel.OnDisconnected += TcpClient_OnDisconnected;
// Optional: Enable multithreading (Note: Not supported on WebGL)
// FF8.Network.StartThread();
// Add channel
FF8.Network.AddChannel(tcpClientChannel);
// Connect to server
tcpClientChannel.Connect("127.0.0.1", 8010);
// Send data
tcpClientChannel.SendMessage(Encoding.UTF8.GetBytes("Test Message"));
// Disconnect
tcpClientChannel.Disconnect();
// Close channel
tcpClientChannel.Close();
void TcpClient_OnConnected()
{
LogF8.LogNet($"TCP_CLIENT Connected");
}
void TcpClient_OnDataReceived(byte[] data)
{
LogF8.LogNet($"TCP_CLIENT received data: {Encoding.UTF8.GetString(data)}");
}
void TcpClient_OnDisconnected()
{
LogF8.LogNet($"TCP_CLIENT Disconnected");
}
- Server Implementation MultiNetworkServer.cs
/*----------------------------TCP/KCP Server Usage----------------------------*/
// Create TCP channel
TcpServerChannel tcpServerChannel = new TcpServerChannel("TEST_TCP_SERVER", 8010);
// Create KCP channel
KcpServerChannel kcpServerChannel = new KcpServerChannel("TEST_KCP_SERVER", 8020);
// Set callbacks
tcpServerChannel.OnConnected += TcpServer_OnConnected;
tcpServerChannel.OnDisconnected += TcpServer_OnDisconnected;
tcpServerChannel.OnDataReceived += TcpServer_OnDataReceived;
// Optional: Enable multithreading (Note: Not supported on WebGL)
// FF8.Network.StartThread();
// Add channel
FF8.Network.AddChannel(tcpServerChannel);
// Start listening
tcpServerChannel.Start();
// Close channel
tcpServerChannel.Close();
void TcpServer_OnConnected(int conv, string ip)
{
LogF8.LogNet($"TCP_SERVER connection: {conv} Connected, IP: {ip}");
}
void TcpServer_OnDataReceived(int conv, byte[] data)
{
LogF8.LogNet($"TCP_SERVER received data from connection: {conv}. Data: {Encoding.UTF8.GetString(data)}");
}
void TcpServer_OnDisconnected(int conv)
{
LogF8.LogNet($"TCP_SERVER connection: {conv} Disconnected");
}
WebSocket Protocol Usage
- Client Implementation ExampleWebClient.cs
/*----------------------------WebSocket Client Usage----------------------------*/
// Configuration parameters
private string _address = "ws://127.0.0.1:7778";
private int _maxMessageSize = 32000;
private bool _noDelay = true;
private int _sendTimeout = 5000;
private int _receiveTimeout = 5000;
private int _maxMessagePerTick = 500;
// Set connection scheme to wss (if sslEnabled is true, clientUseWss should also be true)
public bool clientUseWss = false;
private bool echo = false;
private SimpleWebClient client;
private float keepAlive;
// Connect to server
private void Connect()
{
TcpConfig tcpConfig = new TcpConfig(_noDelay, _sendTimeout, _receiveTimeout);
client = SimpleWebClient.Create(_maxMessageSize, _maxMessagePerTick, tcpConfig);
client.onConnect += () => LogF8.LogNet($"Connected to Server");
client.onDisconnect += () => LogF8.LogNet($"Disconnected from Server");
client.onData += OnData;
client.onError += (exception) => LogF8.LogNet($"Server Error: {exception}");
UriBuilder builder = new UriBuilder(_address)
{
Scheme = clientUseWss ? "wss" : "ws"
};
client.Connect(builder.Uri);
}
// Update loop
private void Update()
{
client?.ProcessMessageQueue();
if (keepAlive < Time.time)
{
client?.Send(new ArraySegment<byte>(new byte[1] { 0 }));
keepAlive = Time.time + 1;
}
}
// Cleanup
private void OnDestroy()
{
client?.Disconnect();
}
// Handle received data
private void OnData(ArraySegment<byte> data)
{
LogF8.LogNet($"Received data from Server, length:{data.Count}");
if (echo)
{
if (client is WebSocketClientStandAlone standAlone)
standAlone.Send(data);
else
client.Send(data);
}
}
- Server Implementation ExampleWebServer.cs
/*----------------------------WebSocket Server Usage----------------------------*/
// Configuration parameters
private int _port = 7778;
private int _maxMessageSize = 32000;
private int _maxHandShakeSize = 5000;
private bool _noDelay = true;
private int _sendTimeout = 5000;
private int _receiveTimeout = 5000;
private int _maxMessagePerTick = 5000;
private bool sslEnabled;
private string sslCertJson = "./cert.json";
private SslProtocols sslProtocols = SslProtocols.Tls12;
private SimpleWebServer server;
private bool connection;
private Dictionary<int, byte[]> sent = new Dictionary<int, byte[]>();
// Server initialization
private IEnumerator Start()
{
TcpConfig tcpConfig = new TcpConfig(_noDelay, _sendTimeout, _receiveTimeout);
SslConfig sslConfig = SslConfigLoader.Load(sslEnabled, sslCertJson, sslProtocols);
server = new SimpleWebServer(_maxMessagePerTick, tcpConfig, _maxMessageSize, _maxHandShakeSize, sslConfig);
server.onConnect += (id, ip) => { connection = true; LogF8.LogNet($"New Client connected, id:{id}, ip:{ip}"); };
server.onDisconnect += (id) => LogF8.LogNet($"Client disconnected, id:{id}");
server.onData += OnData;
server.onError += (id, exception) => LogF8.LogNet($"Client Error, id:{id}, Error:{exception}");
// Start server
server.Start(checked((ushort)_port));
yield return new WaitUntil(() => connection);
for (int i = 1; i < 200; i++)
{
yield return Send(i * 1000);
}
}
// Update loop
private void Update()
{
server?.ProcessMessageQueue();
}
// Cleanup
private void OnDestroy()
{
server?.Stop();
}
// Handle received data
private void OnData(int id, ArraySegment<byte> data)
{
LogF8.LogNet($"Received data from Client, id:{id}, length:{data.Count}");
byte[] received = data.Array;
int length = data.Count;
if (length == 1)
return;
byte[] bytes = sent[length];
for (int i = 0; i < length; i++)
{
if (bytes[i] != received[i])
throw new Exception("Data mismatch");
}
sent.Remove(length);
}
// Send data to client
private IEnumerator Send(int size)
{
byte[] bytes = new byte[size];
System.Random random = new System.Random();
random.NextBytes(bytes);
ArraySegment<byte> segment = new ArraySegment<byte>(bytes);
sent.Add(size, bytes);
server.SendOne(1, segment);
yield return new WaitForSeconds(0.5f);
}