Objective Link
Use an included or custom scene component when a reusable detector owns fields, transient state, reset, and an OnCompleted response.
Concepts
Separate progression records from scene components and understand eligibility, order, identity, and terminal state.
A ChapterObjective is not a MonoBehaviour. It is the serialized record inside a Chapter that gives one position a title, stable identifier, conditions, timing gate, start work, completion work, sound choice, and runtime state. The list order determines progression; hierarchy order of scene GameObjects does not.
An Ordered Objective can be completed by an included scene component, a custom Objective subclass, a UnityEvent that calls a public entry point, or external code that calls the active Chapter. It therefore remains useful even when no scene-side detector is needed.
SignalExternalAnimationCompleted.The state becomes Active before delayed start work executes. A completion request can therefore be accepted while the coroutine is waiting; accepted completion stops that pending start routine so late start actions cannot fire afterward.
ObjectiveCompleted(index) is raised immediately before completion actions.Calling TryCompleteObjective(id, false) uses the same acceptance check but marks the row Skipped and omits completion actions. This is an intentional control operation, not a shortcut for a component that should complete normally.
The Identifier is compared with StringComparison.Ordinal; spelling and case must match exactly. The Editor generates identifiers and exposes Copy ID for integrations, but the assisted Objective Link selector should be preferred for scene components. Duplicating an Ordered Objective creates another progression entry; duplicating a linked scene component can create two detectors bound to the same entry, which Validation reports as a duplicate binding.
Deleting the record leaves a linked scene component without a valid target. Moving the component to another Chapter hierarchy does not change its serialized ID automatically; use the assisted repair controls and re-run Validation.
| Control | Serialized result | Scene consequence |
|---|---|---|
| Add Objective | Appends a row with a generated stable ID | Creates or reuses its optional Objective XX container |
| Duplicate | Copies conditions, timing, actions, events, and sound choice under a new ID | A detector is not safely retargeted merely because its GameObject was copied |
| Move Up / Move Down | Changes the next eligible position | Links remain ID-based; gameplay order changes immediately on the next fresh run |
| Delete | Removes that progression record | Any component still storing its ID becomes Missing and must be relinked or removed |
The generated container is an authoring convenience, not the data record. It may hold zero, one, or several scene components, and an Ordered Objective may have no container at all when UnityEvents or project code provide completion. Keep unrelated gameplay objects outside it so duplication and deletion remain understandable.
| State | How it is reached | Can accept normal completion? | Restored later? |
|---|---|---|---|
| NotStarted | The Chapter has not reached the row | No | Default when no terminal record exists |
| Active | Conditions passed and this is the current row | Yes, by exact ID | No |
| Completed | An accepted request ran completion work | No | Yes |
| Skipped | Conditions failed or code requested completion without actions | No | Yes |
| Failed | The row was active or waiting when its Chapter accepted failure | No | No |
Only one row can be Active, even during Start Delay or Wait For External Animation. Those gates delay start actions; they do not make another row eligible. SignalExternalAnimationCompleted() releases the wait but does not complete the Objective.
Use an included or custom scene component when a reusable detector owns fields, transient state, reset, and an OnCompleted response.
Use Objective.CompleteFromEvent() or a small project bridge when an existing component already exposes the exact accepted signal.
Read CurrentChapter and CurrentObjectiveId, then call TryCompleteObjective(exactId) and inspect the returned bool.
All three routes converge on the same acceptance guard. A component may detect a condition early, a UI event may fire twice, or network code may repeat a callback; none can complete a later, missing, already terminal, or differently linked row. See Objective Link and the compiled external-completion example in Complete and Control Progression.
Completed and Skipped are written under the exact Chapter and Objective identifiers. Hydration applies those states without running old start actions, completion actions, UnityEvents, transport, or sounds. Active and Failed are temporary. A row stored as Completed or Skipped is passed over when a Chapter resumes; the next nonterminal row is evaluated normally.
Idempotency is enforced at the progression boundary: the first valid exact request advances; subsequent calls return false because the Chapter already moved. Component-local IsCompleted also suppresses repeated OnCompleted emission after acceptance. Callers that trigger visual or save consequences should react only to the accepted result or documented lifecycle event.
Inspect panel and complete it from a ButtonObjective. Its completion action enables a generator.Charge generator with Required True State panel_read, a two-second Start Delay, and a MultiActionObjective requiring POWER and COOLING.Wait for door animation, enable Wait For External Animation, and release it from the Animation Event. Complete it later from the door controller.Reach exit with a TriggerObjective. Leave its success sound enabled and use On Objective Completion to hide the marker.panel_read true and false. The second row should be Active in the first run and Skipped in the second; no later row should ever become active at the same time.No eligible scene Objective resolves its exact ID. This is acceptable only when a deliberate UnityEvent or code path will complete it; otherwise create or relink a detector.
More than one scene Objective resolves the same Chapter and Objective ID. Keep one detector or give each copied component a distinct row.
Check whether the row completed during Start Delay, still waits for the external animation signal, or was Skipped by its conditions.
Compare the requested ID with CurrentObjectiveId, including case, and confirm both Chapter and row are Active.
Inspect Skipped rows and null entries. Conditions are evaluated only when their position is reached; a series of ineligible rows can legitimately finish the Chapter.