Class ScyllaSafeScheduler
UI Toolkit scheduler helpers that pair every scheduled item with an
automatic UnityEngine.UIElements.DetachFromPanelEvent cancellation. Use these in
place of raw host.schedule.Execute(...) so a callback cannot outlive
the panel that owns it.
Inherited Members
Namespace: Scylla.Core.Util.UIToolkit
Assembly: ScyllaCore.dll
Syntax
public static class ScyllaSafeScheduler
Remarks
A scheduled item keeps firing until it is paused or until the panel it lives on is destroyed. Between the moment a host tears down its state and the UnityEngine.UIElements.DetachFromPanelEvent that follows, a callback can still run and reach for something that is already gone. Pausing on detach closes that window.
Each helper also guards the callback itself. A callback that throws is stopped rather than left to repeat the same failure on every tick, and a throw that happens after the host has detached is treated as the expected teardown race and swallowed instead of reported.
The framework convention, per the UI Toolkit Scheduler rule in
code-style.md, is to use these helpers for any recurring or
debounced scheduled item, in runtime panels and editor panels alike.
The editor wrapper Scylla.Core.Editor.ScyllaScheduler forwards
here and differs only in the log category it reports under.
Methods
DebouncedSafe(VisualElement, Action, long, LogCategory)
Creates a one-shot debounced scheduled item that fires
callback after delayMs
milliseconds, and pauses automatically on
UnityEngine.UIElements.DetachFromPanelEvent. Pause the returned item and call
ExecuteLater(long) on it to reset
the debounce window without allocating a fresh scheduler entry.
Declaration
public static IVisualElementScheduledItem DebouncedSafe(VisualElement host, Action callback, long delayMs, LogCategory category = LogCategory.UI)
Parameters
| Type | Name | Description |
|---|---|---|
| VisualElement | host | The visual element whose panel attachment controls the lifetime of the
scheduled item. Must not be |
| Action | callback | The action to invoke after the delay. Must not be |
| long | delayMs | The initial delay in milliseconds before the first fire. |
| LogCategory | category | The log category an unexpected callback failure is reported under. |
Returns
| Type | Description |
|---|---|
| IVisualElementScheduledItem | The created UnityEngine.UIElements.IVisualElementScheduledItem, already scheduled. Call
|
Remarks
Typical debounce pattern when responding to a text field's value-changed event:
var debounce = ScyllaSafeScheduler.DebouncedSafe(root, OnSearchChanged, 300);
searchField.RegisterValueChangedCallback(evt =>
{
debounce.Pause();
debounce.ExecuteLater(300);
});
This reuses the single allocated scheduler entry across every keystroke, avoiding per-keystroke allocations.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
OnceSafe(VisualElement, Action, LogCategory)
Creates a scheduled item that fires callback once on
the next scheduler pass, and pauses automatically on
UnityEngine.UIElements.DetachFromPanelEvent.
Declaration
public static IVisualElementScheduledItem OnceSafe(VisualElement host, Action callback, LogCategory category = LogCategory.UI)
Parameters
| Type | Name | Description |
|---|---|---|
| VisualElement | host | The visual element whose panel attachment controls the lifetime of the
scheduled item. Must not be |
| Action | callback | The action to invoke once. Must not be |
| LogCategory | category | The log category an unexpected callback failure is reported under. |
Returns
| Type | Description |
|---|---|
| IVisualElementScheduledItem | The created UnityEngine.UIElements.IVisualElementScheduledItem. |
Remarks
This is the coalescing primitive: call it when a piece of work should happen once after the current burst of changes rather than once per change. Setting ten properties in a row and scheduling a single flush costs one pass instead of ten.
Unlike DebouncedSafe(VisualElement, Action, long, LogCategory) there is no delay and no expectation that the caller will reuse the entry. Schedule it when work becomes pending, and let it run.
Because repeated scheduling is the expected usage, the detach handler this installs removes itself once the job has run, so calling this a thousand times over an element's life leaves no accumulated handlers behind.
Scheduling is not coalesced for you. Two calls before the first fires run the callback twice, so a caller that wants one flush per burst tracks a pending flag of its own and only schedules when nothing is pending.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
RecurringSafe(VisualElement, Action, long, LogCategory)
Creates a recurring scheduled item that fires callback
every intervalMs milliseconds while
host is attached to a panel, and pauses automatically
on UnityEngine.UIElements.DetachFromPanelEvent.
Declaration
public static IVisualElementScheduledItem RecurringSafe(VisualElement host, Action callback, long intervalMs, LogCategory category = LogCategory.UI)
Parameters
| Type | Name | Description |
|---|---|---|
| VisualElement | host | The visual element whose panel attachment controls the lifetime of the
scheduled item. Must not be |
| Action | callback | The action to invoke on every tick. Must not be |
| long | intervalMs | The tick interval in milliseconds. |
| LogCategory | category | The log category an unexpected callback failure is reported under. |
Returns
| Type | Description |
|---|---|
| IVisualElementScheduledItem | The created UnityEngine.UIElements.IVisualElementScheduledItem. Keep the reference if you need to pause the item manually before the host detaches. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |