Runtime Client Probe
Lightweight runtime fixture, loopback command protocol, and in-memory contract validation.
Table of Contents
- Why an In-Binary Probe?
- Architectural Lifecycle
- The Probe Protocol (
ProbeCommandType) - Embedding the Probe in Your Project
Why an In-Binary Probe?
External tools can tell you that a process launched and made network requests. They cannot tell you:
- Did
Addressables.InitializeAsync()succeed? - Did
Addressables.UpdateCatalogs()find and register the new catalog? - Did
Addressables.LoadAssetAsync<GameObject>("Prefabs/Hero")instantiate without missing component scripts? - How many megabytes of RAM were allocated by the updated bundle?
PatchProof’s Runtime Probe (PatchProofProbe.cs) embeds directly into standalone test binaries to answer these questions with zero ambiguity.
Architectural Lifecycle
The probe is a MonoBehaviour assigned an execution order of -1000 to ensure it wakes up before any game logic executes:
[DefaultExecutionOrder(-1000)]
public class PatchProofProbe : MonoBehaviour
{
public static PatchProofProbe Instance { get; private set; }
[SerializeField] private int probePort = 8898;
// ...
}
+-----------------------------------------------------------------------------+
| Standalone Player Process (Client) |
+-----------------------------------------------------------------------------+
| Awake() -> Parse CommandLine (--patchproof-port, --patchproof-token) |
| Start HTTP Server on http://127.0.0.1:8898/ |
| Listen for incoming JSON-RPC command requests from Editor |
| Dispatch commands to Unity Main Thread via EnqueueMainThread() |
| Execute Addressables operations & assert Content Contracts |
| Return ProbeResponse JSON with full event log & client assertions |
+-----------------------------------------------------------------------------+
The Probe Protocol (ProbeCommandType)
Communication between the Editor and the client binary uses strongly-typed JSON requests defined in ProbeProtocol.cs:
1. ProbeCommandType.Handshake
- Verifies connectivity between Editor and client.
- Returns engine version, Addressables version, operating platform, and current memory footprint.
2. ProbeCommandType.PrepareOwnedCache
- Takes
desiredCacheState(Fresh,WarmOld,Mixed). - Prepares the isolated cache sandbox on the client’s local drive without requiring OS file permissions outside the sandbox.
3. ProbeCommandType.InitializeAddressables
- Dynamically overrides the internal Addressables remote load paths to point to the local staging origin (
http://127.0.0.1:8899/). - Calls
Addressables.InitializeAsync().
4. ProbeCommandType.CheckForUpdate
- Calls
Addressables.CheckForCatalogUpdates(). - Returns the list of modified catalogs discovered on the staging origin.
5. ProbeCommandType.UpdateCatalogs
- Calls
Addressables.UpdateCatalogs(). - Activates new catalog instances into the active Addressables locator list.
6. ProbeCommandType.AssertContract
- Accepts a serialized
ContentContractJSON string. - Iterates through every declared key, loads the asset asynchronously, inspects
loadedObject.GetType(), and validates required component schemas. - Releases the loaded asset handles to clean up memory.
Embedding the Probe in Your Project
Automatic Inclusion (One-Click)
When you build an instrumented player from Tools > PatchProof > Local Update Lab:
- PatchProof automatically instantiates the probe prefab into the initial scene.
- It configures default ports and command-line parsing.
- It compiles the binary with developer-mode symbols.
Manual Inclusion (Existing Projects)
- In your project’s first loading scene (Bootstrap / Splash), create an empty GameObject named
[PatchProof_Probe]. - Attach the
PatchProofProbecomponent. - Ensure Auto Start Server is checked.
- Ensure the script is wrapped in
#if DEVELOPMENT_BUILD || UNITY_EDITOR(PatchProof automatically wraps server startup to prevent probe code from running in final public production builds).
Pro Tip: Security Disclaimers
The probe’s HTTP listener is bound strictly to
127.0.0.1and requires a matching--patchproof-tokenargument passed at process launch. Unauthenticated network requests are rejected with HTTP 403 Forbidden.