Skip to content

v0.6.1

Latest

Choose a tag to compare

@github-actions github-actions released this 26 Oct 04:57
· 2 commits to main since this release
b6ca1c3

Highlights

  • Profiling in one call. profile capture start --frames N --wait waits for the capture and returns the summary. profile capture stop on a capture that already finished returns its result instead of an error, and a 0-frame capture reports PROFILE_EMPTY.
  • Find the allocating script. gcByScript attributes GC.Alloc bytes to the nearest script marker, and gcTop no longer fills up with player-loop containers and engine phase markers.
  • Per-marker stats. profile stats --marker ThreatField.Update reports min/median/p95/max ms, calls per frame, and GC bytes per frame over N frames. Short marker names now resolve everywhere.
  • Smoother commands. scene open, scene inspect, and asset reimport/mkdir/delete take the path as a positional argument; execute --code hoists leading using directives; unity-cli --version prints the package version (0.6.1+<sha>).
  • In our own Play Mode profiling benchmark scenario (GC allocation, CPU time, frame time, and texture count checks), an agent using ucb 0.6.1 finished in about 46% less time and at about 28% lower cost than with ucb 0.6.0. execute latency is unchanged.

Assets

  • com.yhc509.unity-cli-bridge-0.6.1.unitypackage: Unity package (Assets > Import Package > Custom Package…)
  • unity-cli-osx-arm64.tar.gz: CLI for macOS Apple Silicon
  • unity-cli-win-x64.zip: CLI for Windows x64

Or add the package by Git URL: https://github.com/yhc509/unity-cli-bridge.git?path=/unity-package/com.yhc509.unity-cli-bridge#v0.6.1

[0.6.1] - 2026-10-26

Added

  • profile analyze <captureId> with no mode returns the capture summary. hotspots, gcTop, and spikes are under summary.
  • profile analyze --marker accepts a short script name. An exact marker name still wins. Otherwise the name is matched after an Assembly.dll!Namespace:: prefix, a trailing () [Invoke], and parentheses are removed, so ThreatField.Update and ThreatField.Update() resolve Assembly-CSharp.dll!::ThreatField.Update() [Invoke]. One match is used and the response includes resolvedMarker. Several matches return PROFILE_MARKER_AMBIGUOUS with the candidate names. A name that matches nothing includes up to five similar marker names.
  • unity-cli version and unity-cli --version print this CLI's version. It is the Unity package version plus the git revision (0.6.1+<sha>), taken from the package version at build time.
  • Leading using directives in execute --code are hoisted above the wrapper, including a one-line snippet such as using UnityEngine; return Application.unityVersion;. --file already hoisted usings that were on their own lines. The compile cache key is still the wrapped source.
  • profile capture start --wait waits for the capture to finish and returns captureId, capturedFrames, and summary (the profile analyze summary) in one call. It needs --frames or --duration. --timeout <seconds> defaults to 60 s plus 0.25 s per frame (or the duration). On timeout it fails with PROFILE_WAIT_TIMEOUT, which names the captureId and the frames captured so far. The capture keeps running.
  • profile stats --marker <name> (repeatable, up to 10) measures named profiler markers over --frames frames: ms min/median/p95/max, calls per frame, and GC bytes per frame. Names resolve the same way as profile analyze --marker, so ThreatField.Update works. Script markers are recorded only while the profiler runs (checked on Unity 2021.3 and 6000.3), so the command turns the profiler on for the measurement and restores it after. Each result's path says whether the time came from ProfilerRecorder (recorder) or from the profiler frame hierarchy (capture). GC bytes always come from the frame hierarchy.
  • The capture summary and profile analyze --gc add gcByScript: GC.Alloc bytes attributed to the nearest script marker above each allocation, with bytesPerFrame, plus gcUnattributedBytes for allocations with no script marker above them.
  • The profiling guide describes how to compare memory and object counts over time in Play Mode without a fixed sleep. Sample with profile memory and profile memory top (for example --type Texture2D), advance frames with profile capture start --frames <n> --wait, sample again, then profile memory compare the two reports.

Changed

  • Default and compact text output shows identical lines that repeat back-to-back in an execute log once, as line (×N). --json keeps every line.
  • Default and compact text output of a compile failure keeps the diagnostic lines and drops the /define: list and reference list. --json still includes the full message.
  • Compact status omits pipeName and domainId. --json and the default text output still include them.
  • execute --help describes the default Roslyn host (C# 9). mcs is used only when UCB_EXECUTE_COMPILER=codedom.
  • profile capture stop after the capture already finished on its own (--frames or --duration reached, the 600 s cap, or Play Mode ended) returns that capture's captureId, capturedFrames, and summary with notice: PROFILE_ALREADY_COMPLETED instead of PROFILE_NOT_RUNNING. PROFILE_NOT_RUNNING remains for an Editor session with no running and no finished capture.
  • A capture that records 0 frames is no longer reported as Completed. Its status is Empty, and profile capture stop, stop --wait, and start --wait fail with PROFILE_EMPTY (retryable), the captureId, and a hint to retry with --frames <n> --wait.
  • gcTop in the capture summary, profile analyze, and profile analyze --gc leaves out the player-loop containers (PlayerLoop, UpdateScene, BehaviourUpdate, Update.ScriptRunBehaviourUpdate, and the LateUpdate and FixedUpdate equivalents) and GC.Alloc itself. Their GC column is the total of everything below them, so they used to fill the list.
  • Capture sidecars are schemaVersion 2, which adds gcByScript and gcUnattributedBytes. Version 1 sidecars still load. Their gcByScript is empty, and notes says the capture was recorded before GC attribution.
  • scene open accepts the scene path as a positional argument (scene open Assets/Scenes/Foo.unity) as well as --path. scene inspect, asset reimport, asset mkdir, and asset delete do the same: each takes one asset path, and that path may be positional or --path. There is no scene save or scene close. If two different paths are given, the command fails with CLI_USAGE and names both paths. The same path given both ways is accepted. asset delete still requires --force.

Fixed

  • profile capture start still clamps --frames to the profiler buffer (300 frames on Unity 2021.3, 2000 on Unity 6). A clamped capture records up to that buffer and can come back slightly short, because the ring buffer rotates. The finished summary reports capturedFrames (the actual count) next to frameClamp (requested, clamped, bufferLimit). warning and frameClamp are included only when the request was clamped; unclamped start, --wait, and stop responses omit both. requestedFrames is the clamped cap. A --wait timeout check uses --duration, or a --frames count inside the buffer.
  • gcTop and gcByScript leave out engine end-of-frame and PlayerLoop phase markers such as PlayerEndOfFrame, PostLateUpdate, and PostLateUpdate.*. Allocation under those markers is attributed to the nearest script marker above them, or counted as unattributed. Script markers such as ThreatField.Update() stay ranked.
  • profile capture stop --wait returns the same shape as stop on a capture that already finished: captureId, status, capturedFrames, and summary. notice: PROFILE_ALREADY_COMPLETED is set only when the capture had already finished on its own.