DocumentationAzkar Screen StatsCamera Behavior And API

Runtime integration

Camera Behavior And API

Use authoritative camera selection, visibility and configuration properties, snapshots, custom rows, and project-owned input callbacks.

  • Camera resolution
  • Visibility and configuration
  • Snapshot and custom stats
  • Input and sample

The overlay renders as scene geometry selected for one Game camera. Automatic selection is convenient in simple scenes; assign Target Camera explicitly for split-screen, camera stacks, minimaps, runtime-created cameras, or any project where one view owns the diagnostics.

Camera Resolution

When Target Camera is assigned, that camera is authoritative. If it becomes inactive, disabled, non-Game, or otherwise unusable, the overlay waits. It does not silently move to another view.

When Target Camera is empty, resolution proceeds through:

  1. The current usable attachment.
  2. Camera.main.
  3. Another active, enabled camera with CameraType.Game.

The selected camera must have a non-empty culling mask and valid pixel viewport. AttachedCamera reports the selected attachment; it can retain the last camera while hidden and can be null while disallowed or waiting for a usable camera.

Visibility API

Visibility changes do not disable the user's GameObject:

using Azkar.ScreenStats;
using UnityEngine;

ScreenStatsOverlay overlay = GetComponent<ScreenStatsOverlay>();

overlay.Show();
overlay.Hide();
overlay.Toggle();

bool requestedVisible = overlay.Visible;
overlay.Visible = true;

Visible is the requested state. IsActive additionally accounts for Build Scope, component state, and GameObject state.

Runtime Configuration

Validated properties expose the supported configuration surface without exposing internal buffers:

overlay.BuildScope = ScreenStatsBuildScope.EditorAndDevelopment;
overlay.TargetCamera = gameplayCamera;
overlay.Corner = OverlayCorner.TopRight;
overlay.Margin = new Vector2(12f, 12f);
overlay.Scale = 2f;
overlay.AutoFitSmallViews = true;
overlay.RespectSafeArea = false;

overlay.TextRefreshRate = 4;
overlay.GraphRefreshRate = 12;
overlay.Sections = ScreenStatsSections.Standard;
overlay.GraphCeilingMilliseconds = 33.33f;
overlay.TargetFramesPerSecond = 60f;
overlay.ShowBudgetStats = true;
overlay.ColorGraphByBudget = true;
overlay.ShowBackdrop = true;

Camera attached = overlay.AttachedCamera;
ScreenStatsSnapshot latest = overlay.Snapshot;
bool completeLayoutFits = overlay.ContentFits;
bool textWasTruncated = overlay.TextWasTruncated;

Numeric setters clamp or normalize input to the documented inspector limits. Configure the overlay before showing it where practical so only the necessary state is rebuilt.

Prewarm() creates reusable resources for an allowed, active, enabled component when predictable first-show work is preferable to lazy creation. It does nothing while the component is disabled, its GameObject is inactive, or Build Scope disallows the current player.

Snapshot

Snapshot is a retained read-only struct updated when overlay text is rebuilt. Reading it does not force collection or a refresh. A hidden, disabled, or build-disallowed overlay keeps its most recently built snapshot until another allowed text rebuild; use an application-owned timestamp if snapshot age matters.

The snapshot exposes numeric measurements, availability flags, budget summaries, and status. It intentionally does not include:

  • Formatted overlay text.
  • Device-detail strings.
  • Custom-row labels, units, or values.
  • Individual graph-history samples.

Check source-specific availability before consuming values:

  • HasFrameSample for FramesPerSecond and FrameMilliseconds.
  • CpuAvailable, GpuAvailable, ManagedMemoryAvailable, and SystemMemoryAvailable for their values.
  • Each draw, batch, triangle, and vertex availability flag independently. RenderCountersAvailable means at least one render counter is available.
  • RecentFrameSampleCount >= 100 before treating P99 and 1% low as warmed.
  • TextTruncated for the truncation state captured at that text refresh.

Repeated snapshot reads did not allocate managed memory in retained tests and the Development-player profile. That measured access behavior is not a promise about unrelated consumer code or every project update loop.

Custom Numeric Rows

Project-owned diagnostics can populate four fixed slots without a registration system or callback polling:

overlay.SetCustomStat(0, "Players", playerCount, "online");
overlay.SetCustomStat(1, "Latency", latencyMilliseconds, "ms");
overlay.SetCustomStatUnavailable(2, "Jobs", "queued");

overlay.ClearCustomStat(1);
overlay.ClearCustomStats();
overlay.ShowCustomStats = false;

SetCustomStat, SetCustomStatUnavailable, and ClearCustomStat return false for indices outside 0–3. Setting either a value or explicit unavailable state enables the custom section; clearing a row does not change section visibility.

Input Ownership

Legacy Toggle Key defaults to None, so no global shortcut is polled. When a non-None key is selected and the legacy Input Manager is compiled, the enabled component polls that key.

Projects using Unity's Input System or a custom framework should keep the legacy key at None and connect a user-owned Input Action, debug menu, console command, or button to Show(), Hide(), or Toggle().

using Azkar.ScreenStats;
using UnityEngine;

public sealed class DebugOverlayToggle : MonoBehaviour
{
    [SerializeField] private ScreenStatsOverlay overlay;

    public void OnToggleRequested()
    {
        overlay.Toggle();
    }
}

Bootstrap Sample

The optional Basic Screen Stats Bootstrap sample is development-gated by default and input-system-neutral. Its developmentBuildsOnly option can disable that gate; the overlay's separate Build Scope must also allow the current player. The sample reuses a configured or discovered overlay, including inactive objects, before creating one; can preserve an eligible root object across scenes; and exposes public ShowOverlay(), HideOverlay(), and ToggleOverlay() callbacks for project-owned events.

It never deletes pre-existing duplicates or detaches a user object merely to persist it. Projects with an existing lifetime service or debug framework should use that owner instead.