On Failure does not run
Log the return value. Any result other than Failed means the request was rejected before events.
Runtime
Request failure explicitly, interpret its result, observe the two notifications, and keep restart policy in project code.
The system does not infer defeat from health, time, player death, or a stalled Objective. Game code must call ChapterManager.TryFailCurrentChapter(reason). The request is accepted only after the Manager is ready, while one Chapter is active, and when no scene transition is running.
Accepted failure changes state and raises notifications. It does not load a scene, restore a checkpoint, reposition the player, persist Failed, or display UI automatically.
| Result | When it occurs | Recommended response |
|---|---|---|
Failed | The Chapter was Active and accepted failure. | Allow listeners to apply the game's policy. |
ManagerNotReady | Initialization has not finished. | Wait for On Manager Ready. |
NoActiveChapter | No current Chapter exists. | Review startup selection. |
TransitionInProgress | Another scene is already loading. | Ignore the request and avoid opening another defeat flow. |
ChapterNotActive | The Chapter is Completed, Failed, or Not Started. | Do not replay historical failure. |
The Manager rejects invalid states without side effects.
Chapter becomes Failed; its active or waiting Objective becomes Failed.
ChapterFailed receives ChapterFailureInfo with Chapter, Objective, and reason.
On Failure runs with no arguments for Inspector listeners.
The game chooses UI, retry, reload, or transition behavior.
TryFailCurrentChapter("manual_test").ChapterFailed when the listener needs reason or affected Objective data.ChapterNotActive and emit no new notifications.After Failed, game code can call TrySelectChapter, ReloadCurrentScene(true), TransitionToScene, or its own loader. Choose one policy and run it from a failure listener. HandleFailure remains for legacy UnityEvents, but its parameter is now diagnostic reason text and no longer chooses a restart point.
Active and Failed are transient and are not restored as historical progress. See Progress State Persistence.
Log the return value. Any result other than Failed means the request was rejected before events.
This is expected. Add an external policy and call the chosen transition explicitly.
Check whether the same consequence listens to both ChapterFailed and On Failure.
The product does not persist Failed. Inspect project-owned state or duplicate subscriptions.
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 FailureRequestExample : MonoBehaviour
{
public ChapterFailureResult RequestPlayerDefeat()
{
ChapterManager manager = ChapterManager.Instance;
return manager != null
? manager.TryFailCurrentChapter("player_defeated")
: ChapterFailureResult.ManagerNotReady;
}
}
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 DeathScreenExample : MonoBehaviour
{
[SerializeField]
private GameObject deathScreen;
private ChapterManager manager;
private void OnEnable()
{
manager = ChapterManager.Instance;
if (manager != null)
{
manager.ChapterFailed += ShowDeathScreen;
}
}
private void OnDisable()
{
if (manager != null)
{
manager.ChapterFailed -= ShowDeathScreen;
}
}
private void ShowDeathScreen(ChapterFailureInfo information)
{
if (deathScreen != null)
{
deathScreen.SetActive(true);
}
}
}
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 RestartAfterFailureExample : MonoBehaviour
{
private string failedChapterId = string.Empty;
public void RememberFailure(ChapterFailureInfo information)
{
failedChapterId = information.Chapter != null
? information.Chapter.Identifier
: string.Empty;
}
public bool TryRestartFailedChapter()
{
ChapterManager manager = ChapterManager.Instance;
return manager != null && !manager.IsTransitioning &&
!string.IsNullOrWhiteSpace(failedChapterId) &&
manager.TrySelectChapter(failedChapterId);
}
}