InterestProbe
A client-side watchdog for interest management and content streaming: once a second it writes one machine-parsable line saying what this client can currently see and whether any of it is wrong.
Nebula · Packages/com.1by3.nebula/Runtime/Debug/InterestProbe.cs[DisallowMultipleComponent]
public sealed class InterestProbe : MonoBehaviourA client-side watchdog for interest management and content streaming: once a second it writes one machine-parsable line saying what this client can currently see and whether any of it is wrong. Meant for headless bot clients in a soak run — nebula logs bot1 \| grep nebula-probe is then a time series you can assert on — but it costs nothing to leave on a player client while tuning.
It lives in the package rather than in a game because the four things worth failing a soak on are framework-level, not game-level: replicas leaking past the exit radius (hysteresis or unsubscribe is broken), a net id spawned twice without a despawn in between (a re-entry racing a late despawn), a replica standing in a chunk this process has not loaded (entity traffic overtook container ownership), and a replica count that grows with world size instead of staying bounded.
The line is key=value pairs after a fixed [nebula-probe] tag, so a log parser can split on spaces and never has to track the field order:
[nebula-probe] t=12.0 pos=64.2,0.0,-31.5 cell=1,0,-1 replicas=37 near=12 dmin=3.4 dmax=131.8
beyond=0 dup=0 chunks=25 orphans=0 spawns=41 despawns=4Fields
IntervalSeconds
public float IntervalSeconds = 1f;Seconds between lines. One per second is small enough to leave on for hours and dense enough to see a leak appear.
SlackMeters
public float SlackMeters = 24f;Meters past InterestRadius + InterestExitMargin a replica may sit before it is counted in beyond. Not zero: a replica is measured against a pose that is one interpolation delay old and the gateway evaluates at InterestEvalHz, so a few meters of overshoot is correct behavior and only a persistent count is a bug.
SlackSeconds
public float SlackSeconds = 1.6f;Seconds of the client's own motion added to SlackMeters. An entity may only leave a set after it has been beyond the exit radius for InterestLingerSeconds, the gateway re-evaluates at InterestEvalHz, and the pose measured here is an interpolated one a few ticks old. A walking player covers a meter or two in that window and the flat slack absorbs it, but a client in a ship at 60 m/s leaves everything it holds tens of meters behind entirely correctly. Without this the probe reports a leak every time anyone flies.
Log
public bool Log = true;Also write the line through NebulaLog at info level (on by default; a bot's log is the point).
Properties
LastLine
public string LastLine { get; } = "";The most recent line, for a debug overlay or a test that would rather read than parse a log.
Duplicates
public int Duplicates { get; }Spawns
public int Spawns { get; }Despawns
public int Despawns { get; }Orphans
public int Orphans { get; }Beyond
public int Beyond { get; }Carrierless
public int Carrierless { get; }Replicas riding in a dynamic container whose carrier this client does not hold. A carrier and everything it carries enter and leave a client's set as one unit, so a passenger without its ship is the observable failure of that rule: the client would render a seated player hanging in the air where the ship used to be, and the pose it receives is relative to a frame it cannot resolve.
Methods
Attach
public static InterestProbe Attach(NebulaClient client);Attach a probe to the object holding client (idempotent).