Demo
DebugDemo
Inspect live Chapter and Objective identity, state changes, failure, and transition signals while testing an integration.
Observe public state without changing it
DebugDemo is a development pattern for logging Manager readiness, current Chapter/Objective identity, transition state, and typed failure context. It is valuable when integrating UI, save, dialogue, or movement because it distinguishes “the external signal never arrived” from “Core rejected a stale or wrong-ID request.”
The observer should never call completion, selection, failure, or transition from its logging callbacks. That separation keeps diagnostics from altering the problem being measured.
Signals and properties to expose
| Source | Record | Interpretation |
|---|---|---|
| OnManagerReady | CurrentChapterId, CurrentObjectiveId, states | Initial selection attempted |
| Chapter.ObjectiveCompleted | Chapter ID and accepted index | Pre-completion-action boundary |
| ChapterFailed | Chapter, Objective, Reason | Accepted final failure state |
| OnBeforeSceneLoad | IsTransitioning | Accepted transition is about to persist handoff/load |
| Periodic snapshot | Active flags and IDs | Current observation, not event history |
Use the observer during an integration test
- 1Add the observer to a Demo-only GameObject and ensure it subscribes after the Manager exists.
- 2Run the intended external action and record the state immediately before its callback.
- 3Inspect the callback's completion result. If false, compare its expected ID with CurrentObjectiveId.
- 4Test one duplicate callback and one scene unload. Confirm no duplicate listener or stale singleton remains.
- 5Disable verbose diagnostics in a release player.
Diagnostic limits
- Logging does not prove a physics callback or vendor event is configured correctly; instrument that source too.
- Hydrated state has no historical events to replay.
- OnBeforeSceneLoad is parameterless and does not identify the destination.
- A polling UI can see the next Objective by the time a component OnCompleted callback runs.
- High-frequency Console logging allocates and can distort performance measurements.
The compiled observer below demonstrates safe subscription and cleanup using only public API.
Build a public-API diagnostic observer
- Where to place it
- Use this only on a Demo or development diagnostics GameObject and exclude it from production staging if unnecessary.
- When to call it
- It records Manager readiness, accepted transitions and failures while the component is enabled.
- Behavior
- The observer never changes progression. Logging every event may be noisy and should remain disabled in a release player.
using System;
using System.Collections;
using System.Collections.Generic;
using OverFuture.ChapterObjectiveSystem.Chapters;
using OverFuture.ChapterObjectiveSystem.Events;
using OverFuture.ChapterObjectiveSystem.Objectives;
using OverFuture.ChapterObjectiveSystem.Persistence;
using OverFuture.ChapterObjectiveSystem.Progression;
using UnityEngine;
public sealed class DebugDemoObserverExample : MonoBehaviour
{
private ChapterManager manager;
private void OnEnable()
{
manager = ChapterManager.Instance;
if (manager == null)
{
return;
}
manager.OnManagerReady.AddListener(LogState);
manager.OnBeforeSceneLoad.AddListener(LogState);
manager.ChapterFailed += LogFailure;
}
private void OnDisable()
{
if (manager == null)
{
return;
}
manager.OnManagerReady.RemoveListener(LogState);
manager.OnBeforeSceneLoad.RemoveListener(LogState);
manager.ChapterFailed -= LogFailure;
manager = null;
}
private void LogState()
{
if (manager != null)
{
Debug.Log(
$"Chapter={manager.CurrentChapterId}, " +
$"Objective={manager.CurrentObjectiveId}, " +
$"Transitioning={manager.IsTransitioning}",
this);
}
}
private void LogFailure(ChapterFailureInfo information)
{
Debug.Log($"Failure: {information.Reason}", this);
}
}