Unity Integration Guide
This page is a structure and pseudocode guide, not a downloadable Unity project. For a runnable first-event check, use the local H5 starter before adapting the protocol to your game's existing WebSocket library.
Unity clients should follow the same protocol flow as JavaScript clients:
- Scan
127.0.0.1:49152-65535in bounded parallel batches. - Connect to
/v1/third-party. - Validate
SERVER_HELLO. - Send
AUTH. - Wait for
AUTH_RESULT.success=true, then dispatchEVENTmessages by event name.
Recommended structure
LiveStudioGatewayClient
├─ PortScanner
├─ WebSocketTransport
├─ Authenticator
├─ EventDispatcher
└─ ReconnectPolicyPseudocode
const int PortStart = 49152;
const int PortEnd = 65535;
const int ScanBatchSize = 128;
for (var batchStart = PortStart; batchStart <= PortEnd; batchStart += ScanBatchSize)
{
var batchEnd = Math.Min(batchStart + ScanBatchSize - 1, PortEnd);
var attempts = Enumerable.Range(batchStart, batchEnd - batchStart + 1)
.Select(port => ConnectAndValidateHello(
$"ws://127.0.0.1:{port}/v1/third-party",
timeoutMs: 500));
var candidates = await Task.WhenAll(attempts);
var socket = candidates.FirstOrDefault(candidate => candidate != null);
if (socket == null) continue;
foreach (var candidate in candidates.Where(candidate => candidate != null && candidate != socket))
await candidate.Close();
await socket.SendJson(new
{
type = "AUTH",
app_id = appId,
key_id = keyId,
secret = secret,
version = "1.0.0"
});
StartReceiveLoop(socket);
break;
}ConnectAndValidateHello returns a socket only when the first message is the supported SERVER_HELLO; it closes failures, timeouts, malformed messages, and incompatible versions. Keep concurrency bounded and never open all 16,384 candidates at once.
Event dispatch
void HandleEvent(EventEnvelope envelope)
{
switch (envelope.Event)
{
case "live.like":
HandleLike(envelope.Payload);
break;
case "live.gift":
HandleGift(envelope.Payload);
break;
case "live.chat":
HandleChat(envelope.Payload);
break;
}
}Map gifts to gameplay effects
Choose IDs in the Gift Catalog and store them as strings in configuration. Resolve the rule before dispatching the actual gameplay work to Unity's main thread.
readonly Dictionary<string, Action<int>> giftEffects = new()
{
["5655"] = count => SpawnRoses(count),
["6064"] = _ => ShowBanner("GG!"),
["7569"] = _ => ActivateControllerBoost(),
};
void HandleGift(LiveGiftPayload payload)
{
if (!giftEffects.TryGetValue(payload.Gift.Id, out var effect)) return;
if (!payload.RepeatEnd) return;
var count = int.TryParse(payload.RepeatCount, out var parsed) && parsed > 0
? parsed
: 1;
mainThreadQueue.Enqueue(() => effect(count));
}The catalog is only an authoring snapshot. Unknown IDs should be ignored or routed to a generic fallback without interrupting the receive loop.
Unity-specific notes
- Dispatch gameplay changes back to Unity's main thread.
- Keep one active gateway connection per application.
- Avoid reconnecting every frame after a failure.
- Do not store the raw
secretin scenes, prefabs, or logs. - Use
message_idto deduplicate events before driving gameplay.
