Quest Manager

QuestManager.cs

Overview

QuestManager is the central authority of the Quest Forge system. It owns all quest state — tracking which quests are active, completed, failed, or abandoned — and provides the public API for starting, completing, failing, and abandoning quests. It also listens to the QuestEventBus to automatically advance quest objectives as gameplay events occur, manages the Quest Journal UI, drives the HUD tracker display, and runs per-frame objective distance calculations.

QuestManager is a singleton MonoBehaviour resolved via QuestManager.Instance. It should be present in the scene as part of the QuestForgeManagers prefab.

Inspector Properties

Quest Registry

Property
Description

All Quests

The master list of every Quest ScriptableObject in the game. Quests must be registered here to be tracked or started.

Debug Mode

Enables verbose logging via QuestLogger for all quest state changes and event processing.

Give Quest Animation

When enabled, the NewQuestPanel animation plays on quest start, completion, and failure. The panel waits for any in-progress dialogue to finish before displaying.

UI References

Property
Description

Quest Journal UI

The root GameObject of the Quest Journal panel. Toggled by OpenQuestJournal() / CloseQuestJournal().

Quest UI Child Prefab

Prefab instantiated for each quest entry in the journal's quest list.

Quest Category Header Prefab

Prefab used to create category headers (Active, Completed, Failed) in the journal list.

Objective UI Child Prefab

Prefab instantiated for each objective in the journal's objective panel.

Quest Reward UI Child Prefab

Prefab instantiated for each reward shown in the journal's reward panel.

Quest UI Parent

The Transform (ScrollView content) that quest list items are parented to.

Objective UI Parent

The Transform (ScrollView content) that objective items are parented to.

Rewards UI Parent

The Transform (ScrollView content) that reward items are parented to.

No Quests / No Objectives / No Rewards Panel

GameObjects shown when the corresponding list is empty.

New Quest Panel

The notification panel shown on quest start, completion, or failure.

Quest Name Text

TextMeshProUGUI displaying the name of the currently selected journal quest.

Quest Description Text

TextMeshProUGUI displaying the description of the currently selected journal quest.

Current Tracked Quest UI Text

HUD element displaying the name of the currently tracked quest.

Current Tracked Quest Current Objective UI Text

HUD element displaying the current objective progress text for the tracked quest.

Objective Animation

Property
Description

Objective Animator

Animator triggered with "ObjectiveChange" when the tracked quest's current objective text changes.

Tracked Icon

GameObject shown when a quest is actively tracked. Hidden when nothing is tracked.

Text Fade Duration

Duration in seconds for the fade transition when the tracked objective text changes.

Quest Objective Distance Tracking

Property
Description

Enable Objective Tracking

Toggles per-frame distance calculation for all active quest objectives.

Show Distance To Objectives

Controls whether distance text is generated.

Distance Format

Format string for distance display (e.g. "0m"125m, "0.0m"125.5m).

Use Metric Units

When enabled, displays metres. When disabled, multiplies by Meters To Feet and displays in feet.

Meters To Feet

Conversion multiplier when imperial units are used (default 3.28084).

Objective Highlighting

Property
Description

Highlight Tracked Objectives

Enables the pulse highlight colour effect for tracked objective markers.

Tracked Objective Color

Target colour for the pulse animation on tracked objectives.

Tracked Objective Pulse Speed

Speed of the PingPong pulse cycle.

Tracked Objective Scale Multiplier

Scale factor returned for tracked objectives to increase their marker size.

Distance Ranges

Property
Description

Close Range

Distance threshold (metres) below which closeRangeColor is returned. Default 25.

Medium Range

Distance threshold (metres) below which mediumRangeColor is returned. Default 100.

Close / Medium / Far Range Color

Colours returned to callers for distance-based UI colouring (green / yellow / red by default).

Priority System

Property
Description

Prioritize Closest Objective

Orders GetPriorityObjectives() results by tracked status, required status, then distance.

Max Visible Objectives

Maximum number of results returned by GetPriorityObjectives().

Player Reference

Property
Description

Player Transform

TransformReference pointing to the player. Used for distance calculations and as instigator on events.

Auto Find Player

If enabled and Player Transform is not set at runtime, searches for a GameObject tagged "Player" on Start.


Malbers Events

These MEvent fields appear at the top of the component and are fired globally in addition to any quest-specific events:

Event
Fires When

EnemyKilledEvent

(Legacy integration point) — an enemy kill is reported via the legacy HandleEnemyKilled path.

ItemCollectedEvent

(Legacy integration point) — an item collection is reported via the legacy HandleItemCollected path.

LocationReachedEvent

(Legacy integration point) — a location is reported via the legacy HandleLocationReached path.

NPCTalkedToEvent

(Legacy integration point) — an NPC interaction is reported via the legacy HandleNPCTalked path.

OnQuestAbandoned

MEvent(string) — a quest is abandoned. Passes the quest ID.

OnQuestCompleted

MEvent(string) — a quest is completed. Passes the quest ID.

OnQuestFailed

MEvent(string) — a quest is failed. Passes the quest ID.

OnQuestStarted

MEvent(string) — a quest is started. Passes the quest ID.

UnityEvent

Event
Type
Fires When

OnRewardGranted

UnityEvent<QuestRewardBase, QuestInstance>

A reward is successfully granted on quest completion. Passes the reward and the quest instance.

Quest Lifecycle API

StartQuest(string questId)bool

Starts a quest by its ID. Returns true if successful.

Checks:

  • Quest must exist in allQuests

  • Quest must not already be active or completed (unless Repeatable)

  • Quest must not be in the failed list

  • All prerequisite quests must be completed (or at least one, if PrerequisiteMode is RequireAny)

On success:

  • Creates a new QuestInstance, sets status to Active

  • Subscribes the quest's objectives to the event bus

  • Fires Quest.OnQuestStarted, QuestManager.OnQuestStarted (MEvent)

  • Publishes QuestProgressEventData with type QuestStarted to the event bus

  • Displays the New Quest Panel animation (if Give Quest Animation is enabled, waits for active dialogue to finish first)


StartQuestWithID(string id)

Non-returning wrapper around StartQuest. Suitable for use as a Unity Event target.


CompleteQuest(string questId)bool

Completes an active quest by its ID. Returns true if successful.

On success:

  • Moves the quest from activeQuests to completedQuests

  • Grants all rewards via GrantQuestRewards()

  • Fires Quest.OnQuestCompleted, QuestManager.OnQuestCompleted (MEvent), OnRewardGranted (UnityEvent) per reward

  • Publishes QuestProgressEventData with type QuestCompleted

  • Re-evaluates which quests are now available (RefreshAvailableQuests)

  • Displays the Quest Complete Panel animation


FailQuest(string questId)bool

Fails an active quest by its ID. Returns true if successful.

On success:

  • Moves the quest from activeQuests to failedQuests

  • Fires Quest.OnQuestFailed, QuestManager.OnQuestFailed (MEvent)

  • Publishes QuestProgressEventData with type QuestFailed

  • Displays the Quest Failed Panel animation


AbandonQuest(string questId)bool

Abandons an active quest by the player's choice. Returns true if successful.

On success:

  • Moves the quest from activeQuests to abandonedQuests

  • Fires Quest.OnQuestAbandoned, QuestManager.OnQuestAbandoned (MEvent)

  • If the quest is Repeatable, adds it back to availableQuests

Quest State Queries

Method
Returns
Description

IsQuestActive(string questId)

bool

Whether the quest is currently in the active state.

IsQuestCompleted(string questId)

bool

Whether the quest has been completed.

IsQuestAvailable(string questId)

bool

Whether the quest's prerequisites are met and it can be started.

GetActiveQuest(string questId)

QuestInstance

The active QuestInstance for the given ID, or null.

GetActiveQuests()

List<QuestInstance>

All currently active quest instances.

GetCompletedQuests()

List<QuestInstance>

All completed quest instances.

GetFailedQuests()

List<QuestInstance>

All failed quest instances.

GetAbandonedQuests()

List<QuestInstance>

All abandoned quest instances.

GetAvailableQuests()

List<Quest>

All Quest ScriptableObjects that can currently be started.

GetAvailableQuestIds()

List<string>

IDs of all quests that can currently be started.

GetActiveQuestCount()

int

Total number of currently active quests.

GetCompletedQuestCount()

int

Total number of completed quests.

GetQuestDefinition(string questId)

Quest

The Quest ScriptableObject for a given ID, from allQuests.

ForceRefreshAvailableQuests()

void

Re-evaluates all prerequisite checks and rebuilds the available quests set. Call after loading a save.


Objective State Queries

Method
Returns
Description

IsObjectiveCurrentlyActive(string questId, string objectiveId)

bool

Returns true if the specified objective is the current active (first incomplete) objective in its quest.

IsObjectiveCompleted(string questId, string objectiveId)

bool

Returns true if the specified objective has been completed in an active quest.


Quest Tracking API

Only one quest can be tracked at a time. The tracked quest is displayed on the HUD and drives the minimap/compass objective indicator.

Method
Description

TrackQuest(QuestInstance quest)

Sets the given quest as tracked. Automatically untracks all other active quests.

UntrackQuest(QuestInstance quest)

Removes tracking from the given quest.

UntrackAllQuests()

Removes tracking from all active quests.

GetCurrentTrackedQuest()

Returns the first QuestInstance with isTracked = true, or null if none.


Objective Distance Tracking API

Each frame (when Enable Objective Tracking is on), QuestManager builds a Dictionary<string, QuestObjectiveData> mapping objective IDs to their distance data. This data is consumed by the compass, minimap, and any custom UI.

Method
Returns
Description

GetAllObjectiveData()

Dictionary<string, QuestObjectiveData>

All current objective distance data for all active quests.

GetObjectiveData(string objectiveId)

QuestObjectiveData

Distance data for a specific objective ID.

GetClosestObjective()

QuestObjectiveData

The objective with the shortest distance to the player that has a world position.

GetTrackedObjectives()

List<QuestObjectiveData>

Returns only the current active (first incomplete) objective of the tracked quest. Used by the HUD.

GetQuestObjectives(string questId)

List<QuestObjectiveData>

All objective data entries belonging to the specified quest.

GetPriorityObjectives()

List<QuestObjectiveData>

Top N objectives ordered by: tracked first, required before optional, then closest. N is set by Max Visible Objectives.

GetObjectiveWorldPosition(QuestObjective objective)

Vector3?

Returns the world position for an objective — directly from GoToLocationObjective.targetPosition, or from a linked PointOfInterest via POIManager. Returns null if no position can be determined.

ShouldHighlightObjective(string objectiveId)

bool

Returns true if the objective belongs to the tracked quest and highlighting is enabled.

GetObjectiveHighlightColor(string objectiveId, float pulseTime)

Color

Returns the pulsed highlight colour for the objective based on Time.time. Returns white if not highlighted.

GetObjectiveScaleMultiplier(string objectiveId)

float

Returns trackedObjectiveScaleMultiplier for tracked objectives, 1f otherwise

Quest Journal UI API

These methods are typically called by UI buttons or input handlers.

Method
Description

OpenQuestJournal()

Activates the Quest Journal UI GameObject.

CloseQuestJournal()

Deactivates the Quest Journal UI GameObject.

ToggleQuestJournal()

Toggles the journal open/closed. Will not open if dialogue is currently active. Refreshes quest and objective lists when opening.

PopulateQuestUIList()

Rebuilds the full quest list in the journal, grouped by Active, Completed, and Failed categories.

PopulateObjectiveUIList()

Rebuilds the objective list for currentlySelectedQuest.

PopulateRewardsUIList()

Rebuilds the rewards list for currentlySelectedQuest.

SelectQuest(QuestInstance questInstance)

Sets the given quest instance as the currently selected journal entry and refreshes the details, objectives, and rewards panels.

SelectQuestById(string questId)

Finds a quest by ID (checking active then completed) and selects it.

UpdateCurrentTrackedQuestUI()

Refreshes the HUD tracker text with the current tracked quest name and objective progress. Triggers the fade animation if the objective text has changed.

How It Works

On Awake, QuestManager subscribes to five event types on the QuestEventBus:

  • EnemyKilled → increments kill counts via QuestProgress.AddKill(key)

  • ItemCollected → increments item counts via QuestProgress.AddItem(itemId, quantity)

  • NPCTalkedTo → sets talked_to_{npcId} flags (and talked_to_{npcId}_{dialogueId} if a dialogue ID is present)

  • LocationReached → sets reached_{locationId} flags

  • ObjectInteracted → records interactions via QuestProgress.AddInteraction(id, instanceId) and also tracks by MInteract.Index if provided

After any event is processed, CheckQuestProgress() is called on all active quests. This calls QuestInstance.UpdateObjectiveStatus() and QuestInstance.CheckCompletion(). If all required objectives are satisfied, CompleteQuest() is called automatically.

A QuestProgressEventData event is published to the bus after every progress check, allowing other systems (such as POIMarker visibility logic) to react to objective changes without polling.


Other Notes

  • QuestManager is not DontDestroyOnLoad — unlike QuestEventReporter, it lives in the scene. If you load a new scene, ensure a QuestManager is present or the system will not function. Quest state is maintained via the save system across scene loads.

  • Prerequisite logic supports two modes: RequireAll (all prerequisites must be complete) and RequireAny (at least one must be complete). This is defined on the Quest ScriptableObject.

  • The New Quest / Complete / Fail animations wait one frame after the event fires before checking if dialogue is active. This prevents race conditions when a QuestTrigger and a dialogue trigger fire on the same frame.

  • Repeatable quests re-enter the availableQuests set after abandonment and can be re-entered the availableQuests set after completion if questType is Repeatable.

  • Call ForceRefreshAvailableQuests() after loading a save file to ensure the available quest set correctly reflects the loaded completed quest list.

Last updated