Introduction à la communication cross-platform dans ET
Dans le développement de jeux Unity3D, assurer une communication en temps réel entre les versions WebGL et les clients natifs représente un défi technique. Le framework ET, basé sur une architecture événementielle et un modèle Actor, offre une soultion robuste pour établir des connexions WebSocket persistantes. Cet article détaille une implémentation pratique permettant de synchroniser les interactoins entre les plateformes.
Analyse des options de communication
Plusieurs technologies permettent d'établir des communications réseau en temps réel. Voici une comparaison des méthodes courantes :
| Méthode | Avantages | Inconvénients | Cas d'utilisation |
|---|---|---|---|
| Requêtes HTTP courtes | Simple à implémenter, large compatibilité | Latence élevée, charge serveur importante | Mises à jour non critiques |
| WebSocket | Communication full-duplex, faible latence | Support limité sur anciens navigateurs | Jeux temps réel, systèmes de chat |
| WebRTC | Transmission peer-to-peer, optimisé pour le média | Complexité d'implémentation, problèmes de compatibilité | Applications de visioconférence |
Le framework ET privilégie WebSocket pour sa capacité à gérer des communications bidirectionnelles efficaces, particulièrement adaptée aux environnements de jeu.
Architecture technique d'ET pour WebSocket
L'architecture réseau d'ET repose sur plusieurs composants clés :
- Boîte aux lettres (MailboxComponent) : Gère les files d'attente de messages pour les entités, permettant un traitement asynchrone.
- Système d'événements (EventSystem) : Traite les événements système, y compris les changements d'état de connexion.
- Émetteur de messages Actor : Facilite l'envoi de messages entre processus ou plateformes.
La séquence de communication WebSocket implique l'établissement de la connexion, l'échange de données via des événements, et la gestion des reconnexions automatiques.
Mise en œuvre pratique étape par étape
Configuration du serveur
Pour activer WebSocket sur le serveur ET, initialisez le composant réseau avec les paramètres appropriés :
// Initialisation du serveur WebSocket
var serverConfig = entity.Get<ConfigurationComponent>().Fetch<ServerSettings>();
var networkHandler = entity.AddComponent<NetworkHandler>();
networkHandler.ActivateWebSocketEndpoint(serverConfig.WsPort);
Connexion côté client
Pour WebGL
Sur les plateformes WebGL, utilisez une composante dédiée pour gérer les connexions WebSocket :
public class WebGLSocketAdapter : INetworkAdapter
{
private WebSocket _wsChannel;
public async Task EstablishConnection(string uri)
{
_wsChannel = new WebSocket(uri);
await _wsChannel.ConnectAsync();
// Enregistrement des gestionnaires d'événements
eventSystem.RegisterHandler<SocketMessageEvent>(OnMessageReceived);
}
}
Pour les clients natifs
Les applications natives utilisent une approche TCP via des adaptateurs de composants :
public class NativeTcpAdapter : INetworkAdapter
{
private TcpConnection _connection;
public async Task EstablishConnection(string host, int port)
{
var socketFactory = new SocketFactory();
_connection = await socketFactory.CreateConnection(host, port);
}
}
Traitement des messages
Exploitez le système d'événements d'ET pour dispatcher les messages entrants :
[EventHandler(MessageType.SocketData)]
public class IncomingMessageProcessor : IEventHandler<SocketDataEvent>
{
public void Handle(SocketDataEvent evt)
{
var packet = SerializationHelper.Decode<NetworkPacket>(evt.Payload);
eventSystem.Publish(packet.MessageType, evt.Session, packet.Content);
}
}
Reconnexion automatique
Implémentez un mécanisme de reconnexion robuste avec temporisation :
public async Task RetryConnection(string targetUri, int maxAttempts = 5)
{
for (int attempt = 0; attempt < maxAttempts; attempt++)
{
try
{
await EstablishConnection(targetUri);
logger.Log("Connexion WebSocket rétablie");
break;
}
catch (ConnectionException ex)
{
logger.Error($"Échec de reconnexion : {ex.Message}");
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
}
Synchronisation d'état cross-platform
Utilisez le modèle Actor pour maintenir la cohérence entre les clients :
// Envoi de mise à jour d'état via Actor
var actorProxy = serviceLocator.Get<ActorProxyService>();
var stateMessage = new EntityStateUpdate
{
EntityId = character.Id,
Coordinates = character.Position,
Orientation = character.Rotation
};
await actorProxy.SendMessage<EntityStateUpdate>(stateMessage);
Considérations spécifiques à WebGL
Les environnements WebGL imposent certaines restrictions techniques :
- Les opérations réseau doivent s'exécuter sur le thread principal en raison des limitations de Web Workers.
- Seules les connexions WebSocket sont supportées directement.
- Le stockage local nécessite l'utilisation d'IndexedDB comme alternative à PlayerPrefs.
Optimisation de la sérialisation
Pour améliorer les performences de transmission, adoptez un format de sérialisation compact :
public static class PacketEncoder
{
public static byte[] Serialize<T>(T data)
{
return MessageSerializer.ToBinary(data);
}
public static T Deserialize<T>(byte[] buffer)
{
return MessageSerializer.FromBinary<T>(buffer);
}
}