Skip to content

feat(audience-unity): Unity integration (SDK-146 / 227 / 228)#707

Merged
ImmutableJeffrey merged 3 commits intomainfrom
feat/sdk-146-unity
Apr 27, 2026
Merged

feat(audience-unity): Unity integration (SDK-146 / 227 / 228)#707
ImmutableJeffrey merged 3 commits intomainfrom
feat/sdk-146-unity

Conversation

@ImmutableJeffrey
Copy link
Copy Markdown
Collaborator

@ImmutableJeffrey ImmutableJeffrey commented Apr 24, 2026

Summary

  • Adds Unity integration under Runtime/Unity/ (com.immutable.audience.unity asmdef).
  • DeviceCollector — one-shot capture on the main thread: platform, version, buildGuid, unityVersion, osFamily, deviceModel, gpu, gpuVendor, cpu, cpuCores, ramMb, screenDpi for game_launch; userAgent, locale, timezone, screen for per-event context. String fields capped at 256 chars (mirrors Web SDK's MAX_STRING_LENGTH).
  • UnityLifecycleBridge — forwards OnApplicationPause / OnApplicationFocus (desktop only — mobile focus is noisy) to ImmutableAudience.OnPause / OnResume.
  • AudienceUnityHooks at SubsystemRegistration — wires DefaultPersistentDataPathProvider, LaunchContextProvider, ContextProvider; forwards Application.quitting to Shutdown.
  • ImmutableAudience — adds internal OnPause / OnResume; MergeUnityContext merges ContextProvider output into every outgoing msg.context on the Track and Identify paths.
  • Directory.Build.props redirects bin/obj to repo-root artifacts/ so dotnet output doesn't leak into Unity's asset importer.
  • link.xml preserves Immutable.Audience.Runtime and Immutable.Audience.Unity against IL2CPP stripping.
  • ConstantsTests.ReadPackageJson walks up from the test binary to locate the package root, so the Directory.Build.props redirect doesn't break it.

Linear: SDK-146, SDK-227, SDK-228.

Comment thread src/Packages/Audience/Runtime/Unity/com.immutable.audience.unity.asmdef Outdated
Comment thread src/Packages/Audience/Runtime/com.immutable.audience.asmdef Outdated
Comment thread src/Packages/Audience/Runtime/Unity/DeviceCollector.cs Outdated
@nattb8 nattb8 marked this pull request as ready for review April 24, 2026 04:52
@nattb8 nattb8 requested review from a team as code owners April 24, 2026 04:52
Comment thread src/Packages/Audience/Runtime/Unity/PerformanceCollector.cs Outdated
ImmutableJeffrey and others added 2 commits April 25, 2026 11:17
…ecycle (SDK-146)

AudienceUnityHooks installs on SubsystemRegistration and wires:

- DefaultPersistentDataPathProvider from Application.persistentDataPath
- LaunchContextProvider with DeviceCollector's one-shot game_launch
  fields (platform, version, buildGuid, unityVersion, osFamily,
  deviceModel, gpu*, cpu*, ramMb, screenDpi)
- ContextProvider with userAgent / locale / timezone / screen, merged
  into every outgoing message.context
- Application.quitting -> ImmutableAudience.Shutdown
- UnityLifecycleBridge forwards OnApplicationPause / OnApplicationFocus
  to ImmutableAudience.OnPause / OnResume

New Unity-layer files (Runtime/Unity/):

- DeviceCollector.cs — IL2CPP-safe SystemInfo / Screen / Application
  readers. Strings capped at 256 chars to mirror the Web SDK identifier
  cap (core/src/validation.ts MAX_STRING_LENGTH)
- UnityLifecycleBridge.cs — lifecycle forwarder

Core changes in ImmutableAudience:

- LaunchContextProvider / ContextProvider typed as
  Func<IReadOnlyDictionary<string, object>>? so the cached snapshot
  cannot be mutated by any downstream reader
- MergeUnityContext merges ContextProvider output into every outgoing
  message.context before EnqueueChecked; throws and null returns are
  swallowed so a misbehaving layer cannot drop events

Build and test infrastructure:

- Directory.Build.props redirects bin/obj to repo-root artifacts/ so
  dotnet output doesn't leak into Unity's asset importer scan path
- ConstantsTests walks up from the test binary to find the package
  root so the Directory.Build.props redirect doesn't break it
- com.immutable.audience / .unity asmdefs updated
- link.xml preserves Unity hooks from IL2CPP stripping
- .gitignore adds artifacts/

Tests:

- ContextProvider_Set / _Throwing / _ReturnsNull pin the merge +
  swallow behaviour

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Unity NUnit compat

Unity's com.unity.test-framework ships NUnit 3.5, which predates
Assert.DoesNotThrowAsync. Awaiting the task achieves the same assertion
semantic — NUnit fails the test if the awaited task throws.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
nattb8
nattb8 previously approved these changes Apr 26, 2026
Adds six public diagnostic getters on ImmutableAudience:
- Initialized: true between Init and Shutdown.
- CurrentConsent: live consent level.
- UserId: last Identify value; null below Full consent.
- AnonymousId: anonymous, persistent ID.
- SessionId: current session id; rotates on Init / Reset / timeout.
- QueueSize: number of unsent events (memory + disk).

Each getter is safe from any thread and returns a safe default
when the SDK cannot answer. EventQueue gains an internal
InMemoryCount property so QueueSize can sum without locking.

Adds optional AudienceConfig.BaseUrl override (matches Web/Pixel
SDK pattern; addresses #709 review). Null preserves the key-prefix
derivation; integrations needing a different backend pass the URL
directly.

Tests cover diagnostics lifecycle and BaseUrl resolution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ImmutableJeffrey ImmutableJeffrey merged commit aa40c4a into main Apr 27, 2026
19 checks passed
@ImmutableJeffrey ImmutableJeffrey deleted the feat/sdk-146-unity branch April 27, 2026 01:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

2 participants