The Unity script needs the Editor and the setup listed below. The separate C# companion practice runs in SharpRune without UnityEngine.
Choose the collector model for the actual runtime
Garbage-collector explanations must identify their runtime. Unity 6.0 documents a Boehm-based, non-generational managed collector for its Mono and IL2CPP environment, which differs from desktop CoreCLR's familiar generational model. Do not transfer a claim about cheap generation-zero collections directly into a Unity performance decision. Incremental describes splitting collection work across time; generational describes organizing collection around object ages. Those are different dimensions. A short-lived object can still create collection pressure in Unity even when an ordinary desktop .NET explanation emphasizes a fast young-object allocation path.
The useful application question is which allocations and retained references your actual gameplay produces. Incremental collection can spread supported work across frames, but it neither makes allocations free nor guarantees that every frame avoids interruption. Platform support and Player settings matter; Unity's web platform has different constraints and does not support this incremental mode. Record the real backend and configuration before interpreting a memory capture. SharpRune's console or browser runtime is another environment again, so running the companion does not reveal what a Unity Editor or IL2CPP Player will collect.
Portable C# companion: allocation-volume arithmetic
The SharpRune companion assumes sixty frames each second for sixty seconds, yielding 3600 frames. At 1024 allocated bytes per frame, cumulative requests total 3686400 bytes. At 64 bytes per frame they total 230400, and subtraction gives 3456000 fewer requested bytes. These three printed integers are a workload model with explicit assumptions. They are not a live-heap size, a measured allocation counter or a prediction of reclaimed memory. Objects could become unreachable at different times, remain retained or coexist with unrelated allocations without changing this arithmetic.
long frames = 60L * 60L; long original = 1024L * frames; long reduced = 64L * frames;
Console.WriteLine(original); Console.WriteLine(reduced); Console.WriteLine(original - reduced);Unity Editor: report configuration without forcing GC
CollectorProbe.cs belongs in Unity and only reports configuration and a managed-memory estimate. The context action requires Play mode, prints GarbageCollector.isIncremental and GCMode, and calls GC.GetTotalMemory(false). Passing false does not request that this method force a full collection. The observed estimate may change between calls and excludes a complete accounting of native engine or GPU resources. Compare these labeled observations with Player settings and Profiler evidence. The script does not switch collector modes, establish pause durations or validate that an allocation-reduction strategy benefits the intended device.
[ContextMenu("Report Collector Configuration")]
public void Report()
{
if (!Application.isPlaying) { Debug.LogWarning("Enter Play mode first.", this); return; }
Debug.Log("Incremental: " + GarbageCollector.isIncremental, this);
Debug.Log("Mode: " + GarbageCollector.GCMode, this);
Debug.Log("Managed estimate: " + GC.GetTotalMemory(false), this);
}Incremental work is not a generational nursery
Do not read a lower instantaneous managed estimate as proof of lower cumulative allocations or lower frame-time cost. A pool can reduce repeated allocations while retaining more objects; a texture can consume substantial native memory without appearing as equivalent managed bytes. Removing a reference makes an object potentially collectible only when no relevant path retains it, and collection timing remains a runtime concern. Disabling collection is not a general fix for allocation-heavy gameplay: memory still needs a budget and a safe policy. Measure representative behavior before choosing a specialized collector-control strategy.
Two independent memory-policy exercises
First, independently change the console model to thirty frames per second while keeping a sixty-second interval and both per-frame byte assumptions. Predict 1843200, 115200 and a difference of 1728000. Hint: the frame count halves, so each cumulative amount halves; none of those numbers becomes a collector pause estimate. Then describe a case where total allocation volume falls while retained memory rises, such as keeping a reusable cache. This practice separates arithmetic and retention policy without requiring a Unity installation or inventing a simulated collection algorithm.
Second, use an independent Unity capture to compare a repeated temporary-buffer path with a bounded reusable-buffer path on the intended Player. Record allocations over the same interval and inspect retained managed data separately. Hint: establish the actual incremental flag and backend before interpreting the traces, and include native-memory tools when engine assets are part of the workload. Do not force collections merely to make a graph look tidy during gameplay. State which observed quantity supports the change and which remaining questions, including pause behavior, still need measurements of their own.
Review four different memory questions
Review memory work by asking four separate questions: how much was allocated, what remains reachable, which native resources remain owned, and how much frame time collection consumed. The companion answers only a hypothetical cumulative-volume question; CollectorProbe reports configuration and an estimate; the Profiler supplies actual runtime evidence. Keep Unity's non-generational model distinct from CoreCLR generations and incremental scheduling distinct from guaranteed smoothness. A clear target-specific explanation is more useful than a universal rule about all C# objects, especially when the same language runs inside several very different hosts.
- Name the actual runtime and scripting backend.
- Keep incremental scheduling distinct from generations.
- Treat all three companion numbers as modeled byte volume.
- Separate managed estimates from native memory and pause time.
Unity Editor example
Set up in Unity 6
- Use Unity6.0 (6000.0) documentation as the baseline, not a claim that this is the newest available release.
- Attach CollectorProbe.cs, enter Play mode and invoke Report Collector Configuration.
- Inspect Player settings for incremental GC support on the intended platform and record the actual scripting backend.
- Compare Editor and Player observations without assuming equal memory totals or collection behavior.
- Use the Profiler for allocations and collection timing; do not interpret GC.GetTotalMemory as total native or GPU memory.
CollectorProbe.cs
Download Unity script ↗using System;
using UnityEngine;
using UnityEngine.Scripting;
public sealed class CollectorProbe : MonoBehaviour
{
[ContextMenu("Report Collector Configuration")]
public void Report()
{
if (!Application.isPlaying) { Debug.LogWarning("Enter Play mode first.", this); return; }
Debug.Log("Incremental: " + GarbageCollector.isIncremental, this);
Debug.Log("Mode: " + GarbageCollector.GCMode, this);
Debug.Log("Managed estimate: " + GC.GetTotalMemory(false), this);
}
}
What to observe in Unity
The script reports the actual configuration and a changing managed-memory estimate. Incremental support and values vary by target; the companion arithmetic does not run or emulate Unity’s collector.
The console practice below isolates the C# logic. It does not run a Unity scene or emulate Unity engine callbacks.
C# companion practice
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
long frames = 60L * 60L; long original = 1024L * frames; long reduced = 64L * frames;
Console.WriteLine(original); Console.WriteLine(reduced); Console.WriteLine(original - reduced);
C# practice output
3686400 230400 3456000
Allocation volume, live managed memory, native memory and collection time are different measurements.