Argus

Unity SDK

Everything about installing, configuring, and instrumenting Argus in your Unity project. If you're looking for a 5-minute get-started, see the Quickstart.

Install

Argus ships as a Unity Package Manager (UPM) package called com.argus.profiler. Two install paths:

Local UPM

Download .unitypackage from Tools β†’ Argus Control β†’ πŸ“¦ Export in any project that already has Argus, OR copy the Assets/Argus/ folder to a location outside your target project. Add to Packages/manifest.json:

{
  "dependencies": {
    "com.argus.profiler": "file:../../Packages/com.argus.profiler",
    "com.unity.editorcoroutines": "1.0.0"
  }
}

Git URL

"com.argus.profiler": "https://github.com/argus-profiler/argus-unity.git"

Verify

After Unity reloads, the menu bar shows Tools β†’ Argus Control. If it doesn't, the package didn't compile β€” check the Console for errors.

ArgusConfig

All runtime + editor behaviour reads from a ScriptableObject named ArgusConfig. Create it via Assets β†’ Create β†’ Argus β†’ Configuration and place it in any Resources/ folder. The asset name must be exactly ArgusConfig β€” that's how the runtime finds it via Resources.Load<ArgusConfig>("ArgusConfig").

FieldDefaultWhat it controls
serverUrlhttp://127.0.0.1:3001The Argus dashboard's API host. Set to your deployed backend (e.g. https://argus-api-1579.onrender.com or your custom domain). HTTPS required in production.
uploadCooldown2 sMinimum seconds between batched uploads. Captures pile up in memory until either this elapses or maxPendingSessions is hit.
maxPendingSessions5Force-flush threshold. Hit this many pending captures and the next upload fires immediately regardless of cooldown.
offlineModefalseWhen true, all HTTP uploads are skipped β€” every capture only writes its local _claude.json backup file. Useful for working offline / on planes.
alwaysSaveLocallytrueAlways write the local JSON backup even when the upload succeeds. Recommended on β€” gives you a recoverable copy if the dashboard is down or retention purges the row.
maxFrameBuffer300Per-capture ring-buffer size. 300 frames β‰ˆ 5 seconds at 60 FPS. Older frames silently overwritten when the buffer is full. Bump if you need longer captures.
repeatableEventCooldownSeconds30 sTime-based fallback cooldown for events called with repeatable: true. Default Argus dedup is by (eventName, uniqueId) per test-session run; this only applies to opt-in repeatable callers. See How Argus works.
gcAllocationSampleCount100Max GC-allocation data points included in the local Claude export. Lowers file size; doesn't affect dashboard data.
frameTimeSampleCount100Max frame-time data points per curve in the Claude export. Same trade-off as above.

Argus Control window

Open via Tools β†’ Argus Control. Five panels, top to bottom:

Header strip

Brand wordmark + a toolbar row with πŸ“¦ Export (saves the entire Assets/Argus/ folder as a .unitypackage for sharing) and πŸ“‹ UPM Path (copies the local file:// path to your clipboard so you can paste it into another project's manifest.json). Two status dots on the right: device link and Argus run state.

Connection

Server URL + API key. Status pill shows β—‹ NOT CONNECTED, ● CONNECTED, ● ERROR, or ● OFFLINE.Connect validates the API key against the dashboard and starts profiling; Start Offline bypasses upload entirely (writes local JSON only); Disconnect stops everything.

Test session

The label that wraps every capture you make until you stop. Leave the Label field empty and Argus auto-tags with {ProductName}_{yyyy-MM-dd_HH-mm-ss} (a fresh timestamped label per run). Type a label to override β€” e.g. v0.4.2 RC1 playthrough. Captures uploaded during this period appear under that label on the dashboard.

Environment dropdown stamps every capture with Development / Staging / Production / Testing / Custom β€” useful for filtering on the dashboard later.

Capture

Hot buttons for the per-event recording cycle.β–Ά Start Capture begins a manual recording (you choose when to end it). β–Ά Quick (5s) auto-ends after 5 seconds. ⏹ End Capture while a capture is live finalises + queues for upload. The active-capture state ticks at ~4 Hz so you see the elapsed feel.

AI Export (Claude)

After every capture, Argus writes a dense _claude.json to Application.persistentDataPath/ArgusCaptures/. The Argus skill pack (plugins/argus/skills/) reads these from Claude Code with the /latest and /verify slash commands. Click πŸ“‹ Copy Last Export to put the JSON on your clipboard,or πŸ“ Open Captures Folder to inspect them in Finder/Explorer.

Advanced

Read-only summary of ArgusConfig values + a button to ping the live config asset (jumps to it in the Project window so you can edit it).

Triggering captures from code

The runtime API is one method, two flavours of overload:

using Argus;

// Capture once per (eventName, uniqueId) per test-session run.
// uniqueId is a HUMAN-READABLE name of what the event is about.
Argus.TriggerProfilerEvent(
    "Order.Complete",   // event KIND
    durationSeconds: 3,
    uniqueId: orderConfig.DisplayName);   // SUBJECT, e.g. "Tutorial Order"

// Omit uniqueId when one capture per event KIND is enough.
Argus.TriggerProfilerEvent("Boot.Start", 6);

// repeatable: true bypasses dedup entirely. Every fire captures,
// throttled only by repeatableEventCooldownSeconds (default 30s) for
// spam protection. Use sparingly: A/B perf hunting where every fire
// matters.
Argus.TriggerProfilerEvent("BossFight.Frame", 3, repeatable: true);

Default behaviour: at most one capture per (eventName, uniqueId) pair per test-session run. Same key seen twice in one run = silently dropped. Different uniqueIds for the same eventName fire independently. The dedup table resets when you stop / start the test-session run via Argus Control. See How Argus works for the rationale.

Picking a uniqueId

Mental model: eventName is the KIND of thing happening; uniqueId is the SUBJECT of this specific instance. Pick the same string a developer would say out loud:

EventuniqueId examples
Order.Complete"Tutorial Order", "Boss Order"
Chapter.Complete"Chapter 3 β€” Beach", "Chapter 7 β€” Final"
LevelUp"Level 5", "Level 10"
Window.{TPresenter}omit β€” eventName already encodes the type
Boot.Start / Scene.Load.{sceneId}omit β€” fires once per app boot or once per scene load

Code-region attribution

Wrap any hot code path so frame-time spikes get a human-readable label. Without this, the dashboard can show that a spike happened β€” but not where in code.

using Argus;

void Update() {
    Argus.BeginRegion("EnemyAI.Tick");
    foreach (var enemy in _enemies) enemy.Tick();
    Argus.EndRegion();
}

// Or with the C# 8 'using' scope helper β€” guarantees EndRegion fires
// even on early-return / exception.
void Update() {
    using var _ = Argus.Region("EnemyAI.Tick");
    foreach (var enemy in _enemies) enemy.Tick();
}

Spikes that fire while a region is active are tagged with that region name in the capture's frameSpikes[] and rendered on the dashboard's Top spikes panel as region "EnemyAI.Tick" in scene "Boss_Fight" (dominant: scripts). The Claude latest skill leans on regions for optimisation triage β€” naming 3–5 hot paths is usually enough to make every analysis report point at specific files instead of "look harder".

The API is stack-based β€” nested calls work and the deepest active label wins. BeginRegion / EndRegion are stripped at compile time in DISABLE_CHEATS release builds, so they have zero runtime cost when shipped.

What gets captured automatically

Every capture carries the following without any extra setup:

  • sessionName β€” the test-run label (auto-tagged {ProductName}_{Date} if you don't pick one in Argus Control).
  • appVersion β€” your build's Application.version (PlayerSettings β†’ Other Settings β†’ Version). Lets you correlate regressions to specific builds.
  • Per-spike attribution β€” for each top-10 frame-time spike: the active region, scene name, and dominant subsystem (scripts / render / gc).
  • Full device fingerprint β€” model, OS, RAM, GPU, Unity version, target frame rate.

See Captured data fields for the complete reference.

Release builds (DISABLE_CHEATS)

Argus is dev-only. Define the DISABLE_CHEATS scripting symbol on release-build players (PlayerSettings β†’ Scripting Define Symbols) and every Argus.* entry point becomes a single early return. IL2CPP's linker folds away every Argus call site downstream, so you pay zero runtime cost in release. Call sites in your game code don't need #if guards.

Troubleshooting

SymptomLikely cause + fix
Connection status shows ● ERRORWrong API key, revoked key, or wrong server URL. Re-copy the key from the dashboard's API-keys panel and confirmserverUrl matches your deployed backend.
First device capture takes ~30sFree-tier Render web services sleep after 15 min idle. The first request wakes them. Subsequent captures are instant.
Dashboard shows captures with editor-looking metricsRun the Claude verify skill β€” it diagnoses editor-vs-device data and tells you which Profiler dropdown setting to fix.
Same event firing N times pollutes the dashboardPass uniqueId with a per-instance name, or accept the default first-fire-per-name dedup. See How Argus works.
Argus Control window doesn't appear in Tools menuPackage didn't compile. Check the Console for errors. Often a missing dependency β€” verify com.unity.editorcoroutines is in your manifest.