The Unity script needs the Editor and the setup listed below. The separate C# companion practice runs in SharpRune without UnityEngine.
Session state needs an explicit boundary
Static storage belongs to a managed type rather than to one component instance. A fresh component therefore does not imply a fresh static counter, and leaving Play mode does not always recreate the managed domain. With Unity Editor domain reload disabled, static fields and static event registrations can persist across Play sessions. Faster entry changes a default reset assumption that older code may have relied on. Make the session boundary explicit for state you own instead of assuming that constructing or enabling another scene object clears the application-wide data it can observe.
SessionCounterProbe uses a RuntimeInitializeOnLoadMethod marked SubsystemRegistration to set its owned counter to zero before the new runtime session proceeds. Awake then increments for each instance that actually reaches that callback. The reset establishes a boundary for this field; it does not create a universal ordering system among unrelated services. If several systems depend on shared static state, choose their owner and initialization contract deliberately. A duplicate component in the scene is still a second instance, so resetting once per session does not mean every Awake should report one.
Portable C# companion: reset, count, reset
The SharpRune companion invokes Reset directly, records two Created calls and prints 2. It then resets again, records one creation and prints 1. The second reset changes shared static state rather than constructing a different counter object. These are explicit ordinary C# calls in the order shown, with no Unity attributes or Editor setting changes involved. The result demonstrates a reset policy's arithmetic, not the timing of SubsystemRegistration, Awake or scene reload. Its success cannot establish what callbacks the Editor will invoke under a particular combination of reload options.
SessionCounter.Reset(); SessionCounter.Created(); SessionCounter.Created(); Console.WriteLine(SessionCounter.Count);
SessionCounter.Reset(); SessionCounter.Created(); Console.WriteLine(SessionCounter.Count);
static class SessionCounter { public static int Count { get; private set; } public static void Reset() { Count = 0; } public static void Created() { Count++; } }Unity Editor: reset owned statics before a session
The excerpt belongs to SessionCounterProbe.cs in Unity. Attach it to one saved active scene object, record the Editor's domain and scene reload options separately, and compare two entries into Play mode. The reset method is static and owns exactly the instances field. Keep the full scene setup in view when interpreting logs: the expected count concerns instances whose Awake ran in that session. If scene reload is also disabled, inspect the documented lifecycle effects rather than assuming all scene initialization repeats exactly as it would with both reload settings enabled.
private static int instances;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStatics() { instances = 0; }
private void Awake()
{
instances++;
Debug.Log("Instances this session: " + instances, this);
}Domain reload and scene reload are different controls
Static events can retain handlers as well as data, so resetting a numerical field does not remove stale subscribers. An event publisher should define how owned registrations are cleared or reliably paired with their lifetimes; an unrelated component should not erase all listeners merely to make a test pass. Also distinguish an Editor-only Play-mode hook from a runtime initialization hook used in the script. Recompilation and asset refresh can cause additional reload behavior, so a comparison that changes scripts between runs must record that fact instead of attributing every reset to a single checkbox.
Two independent state-lifetime experiments
First, independently modify the console experiment by omitting only its second Reset. Predict that the final count becomes 3 after the additional Created call, while the first printed line remains 2. Hint: static data survives between these sequential calls because no reset statement intervenes. Restore the reset and move it after the final print to compare ordering. This practice investigates explicit state transitions without requiring Unity and makes it easier to recognize why a per-instance constructor or an unrelated instance cleanup cannot substitute for a correctly placed shared-state boundary.
Second, use a disposable Editor copy and keep scene reload enabled while comparing domain reload enabled and disabled. Remove the reset only in that copy, enter Play mode twice without changing scripts, and record the count behavior; then restore the reset and repeat. Hint: hold one reload setting constant so the experiment has an interpretable cause. In a separate extension, inventory a static publisher's handlers and define publisher-owned cleanup. Do not claim that the counter probe proves event cleanup, because no static event exists in the supplied example.
Review the owner of every static field and event
Finish by naming each piece of shared state, its owner and the session transition that resets it. Explain why domain reload, scene reload, component construction and component enabling are four distinct concerns. A clean counter log proves only the counter's behavior under the recorded setup; it does not prove all other statics or event subscriptions are clean. The portable output remains 2 then 1 from explicit calls. The Editor experiment adds lifecycle evidence and should preserve the actual options, number of instances and any recompilation that could affect the observation.
- Record domain reload and scene reload independently.
- Reset only the static state owned by the responsible service.
- Inventory static event handlers as well as numerical fields.
- Do not infer callback repetition from the console trace.
Unity Editor example
Set up in Unity 6
- Attach SessionCounterProbe.cs to one active object and save the scene.
- Inspect Project Settings > Editor > Enter Play Mode settings and record domain and scene reload choices separately.
- Enter Play mode twice and compare the intended session count with the explicit static reset present.
- In a disposable copy, remove only the reset callback and observe static persistence when domain reload is disabled.
- For static events in a later extension, define which service owns resetting handlers instead of relying on unrelated instance ordering.
SessionCounterProbe.cs
Download Unity script ↗using UnityEngine;
public sealed class SessionCounterProbe : MonoBehaviour
{
private static int instances;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void ResetStatics() { instances = 0; }
private void Awake()
{
instances++;
Debug.Log("Instances this session: " + instances, this);
}
}
What to observe in Unity
The explicit reset establishes a fresh static count for the session. Reload settings affect Editor state lifetime, so comparisons must record the actual domain and scene options.
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;
SessionCounter.Reset(); SessionCounter.Created(); SessionCounter.Created(); Console.WriteLine(SessionCounter.Count);
SessionCounter.Reset(); SessionCounter.Created(); Console.WriteLine(SessionCounter.Count);
static class SessionCounter { public static int Count { get; private set; } public static void Reset() { Count = 0; } public static void Created() { Count++; } }
C# practice output
2 1
An explicit session reset is different from constructing one more instance.