Sonar is a reusable, vendor-independent analytics abstraction for Unity games and applications.
Game code records analytics events through a small stable API. Replaceable providers deliver those events to services such as PostHog, Firebase Analytics, or a custom backend without coupling gameplay code to any one analytics SDK.
Early development release: Sonar is suitable for experiments, prototypes, and package evaluation. The public API is intentionally small and may still change before a stable 1.0 release.
Sonar is for Unity teams that want:
- analytics calls that are easy to test;
- provider choice without rewriting game code;
- a clean boundary between gameplay code and analytics SDKs;
- an open package foundation for future consent, identity, queueing, and provider bridge work.
This repository is structured as a Unity Package Manager package.
Add the package to a Unity 6 project with one of these approaches:
- Clone this repository and add
Packages/com.kostasban.sonarthrough Unity Package Manager's local package flow. - Add the Git URL to
Packages/manifest.jsononce this repository is hosted:
{
"dependencies": {
"com.kostasban.sonar": "https://github.com/KostasBan/Sonar.git?path=/Packages/com.kostasban.sonar"
}
}using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using KostasBan.Sonar;
public static class AnalyticsExample
{
public static async Task RunAsync(CancellationToken cancellationToken)
{
var client = new SonarClient();
var provider = new DebugSonarProvider();
client.RegisterProvider(provider);
client.AddContextProperty("build_channel", "development");
await client.InitializeAsync(cancellationToken);
await client.TrackAsync("game_started", cancellationToken: cancellationToken);
await client.TrackAsync(
"level_completed",
new Dictionary<string, object?>
{
["level_id"] = "forest_01",
["duration_seconds"] = 94.2,
},
cancellationToken);
await client.FlushAsync(cancellationToken);
await client.ShutdownAsync(cancellationToken);
}
}flowchart LR
Game["Game code"] --> Client["SonarClient"]
Client --> Event["SonarEvent"]
Client --> ProviderA["Provider A"]
Client --> ProviderB["Provider B"]
ProviderA --> ServiceA["Analytics service"]
ProviderB --> ServiceB["Custom backend"]
The package currently contains:
SonarEvent: validated event names, UTC timestamps, and immutable properties.ISonarProvider: asynchronous initialize, track, flush, and shutdown operations.SonarClient: explicit construction, context-property merging, multi-provider delivery, independent provider failure handling, and observable failures throughProviderFailed.DebugSonarProvider: in-memory provider with optional injected logging.TestSonarProvider: test utility provider for asserting recorded events.
Sonar targets Unity 6 (6000.0) and keeps runtime code portable where practical. The runtime package has no dependency on UnityEngine or third-party analytics SDKs.
These areas are intentionally documented rather than partially implemented in the first release:
- typed and schema-validated events;
- consent and privacy controls;
- sessions and identity;
- persistent offline queues;
- retry, backoff, and batching;
- rate limiting;
- provider adapters for services such as PostHog and Firebase Analytics;
- optional ecosystem bridges, including Lens and Beacon-driven configuration, in separate bridge packages.
- No production analytics service adapter is included yet.
- No persistent queue or retry policy is included yet.
- No consent, privacy, identity, or session model is included yet.
- Unity edit-mode tests require a Unity installation and may require CI licensing depending on the runner configuration.
The Unity package lives in Packages/com.kostasban.sonar.
CI currently performs package manifest validation, repository layout checks, documentation link checks, and basic formatting/static checks that do not require a Unity license.