POI Marker
Overview
POI Marker is the scene component that makes any GameObject a trackable Point of Interest. Attach it to an NPC, chest, dungeon entrance, or quest target and it will automatically appear as an icon on the minimap, compass bar, and world map.
The component acts as the bridge between the data layer (the PointOfInterest ScriptableObject) and the scene. It self-registers with POIManager on Start, drives its own 3D world-space billboard, and reacts autonomously to changes in quest state, objective progression, and dialogue completion — all without requiring external scripting.
POI Markers support two configuration modes: POI Data mode, where all settings are read from a shared PointOfInterest asset, and Custom Settings mode, where icon, name, colour, and category are set inline on the component itself.

Inspector Sections
POI Configuration
The core identity and lifecycle settings for this marker.
Use Custom Settings
bool
false
When enabled, replaces the POI Data asset slot with inline custom fields. Use for one-off markers that don't need a shared asset.
POI Data
PointOfInterest
—
The ScriptableObject asset supplying this marker's name, icons, colours, and display rules. Shown only when Use Custom Settings is off. A live preview box beneath the slot confirms the asset's name, category, and visibility flags.
Is Active
bool
true
Whether this POI is currently tracked and visible. Can be toggled at runtime via the IsActive property.
Auto Register
bool
true
Calls POIManager.RegisterPOI() automatically in Start. Disable only if you need to control registration timing manually.
Persistent
bool
false
Calls DontDestroyOnLoad in Awake so this POI survives scene transitions.
Custom Settings (only when Use Custom Settings is enabled)
Inline overrides that replace the POI Data asset entirely.
POI Name
string
Display name shown on maps and tooltips.
Map Icon
Sprite
Icon used on the minimap and world map.
Compass Icon
Sprite
Icon used on the compass bar.
Icon Color
Color
Tint applied to both icons.
Category
POICategory
Category used for map filtering. Defaults to Custom.
Location Data (only for Location-category POIs)
When the assigned PointOfInterest asset has its category set to Location, a Location Data section appears showing a live comparison between the position stored in the asset and the marker's current scene transform.
Stored Position (Asset)
Read-only display of the WorldPosition field saved in the POI asset.
Current Position (Transform)
Read-only display of this marker's transform.position.
Sync World Position to Asset
Copies transform.position to the asset's WorldPosition field, marks the asset dirty, and calls AssetDatabase.SaveAssets(). This is the canonical way to set the asset's world position.
Move Marker to Asset Position
Moves this marker's transform to the position stored in the asset. Only works if the stored position is non-zero.
Location Info Preview
Read-only summary of Location ID, type, trigger radius, and parent location pulled directly from the asset.
The inspector warns when the stored position is still at (0, 0, 0), and also warns if the positions have drifted more than 1 metre apart since the last sync.
Location Discovery (only for Location-category POIs)
Controls the physics trigger that fires when the player enters this location's area.
Enable Location Trigger
bool
false
Activates a SphereCollider trigger on this GameObject at runtime. When the player enters, the LocationManager is notified and discovery logic runs.
Use Custom Trigger Radius
bool
false
Overrides the LocationRadius from the POI asset with a per-marker radius.
Custom Trigger Radius
float
50 m
The override radius, shown only when Use Custom Trigger Radius is enabled. The active radius from the asset is shown as a read-only field otherwise.
Auto-Complete Quest Objective
bool
true
Automatically completes any GoToLocationObjective in an active quest whose location ID matches this POI when the player enters.
Trigger Tag
string
"Player"
Only colliders with this tag trigger discovery.
Collider Management — The editor actively validates the collider state:
If no collider is present, the inspector explains one will be created at runtime and offers an Add SphereCollider Now button to add it immediately in edit mode.
If a collider exists but
Is Triggeris off, a warning and an Enable Is Trigger button appear.If a
SphereColliderexists but its radius doesn't match the target radius, a Sync Collider Radius button appears.
Location Events
On Location Entered
The player's collider enters the trigger zone.
On Location Exited
The player's collider leaves the trigger zone.
On Location Discovered
The player enters and this is the first time (the location was not previously discovered).
In Play mode, the Location Discovery section also shows whether the player is currently inside the location, the current discovery status, and a Force Discover (Debug) button that calls TriggerLocationDiscovery() manually.
Quest Integration
Links this POI to a specific quest objective so its visibility is driven automatically by quest progression. The editor uses a two-step workflow:
Step 1 — Select Quest: Drag a Quest ScriptableObject asset into the Linked Quest field. Changing the quest clears any previously selected objective.
Step 2 — Select Objective: A dropdown appears listing every objective in the quest, formatted as index: ObjectiveType — description. Select the objective this POI represents. The Linked Objective ID field is then filled automatically (read-only) and a confirmation box displays the quest name, objective description, type, and whether it is optional.
Additional Settings (shown once a quest and objective are linked):
Hide When Complete
bool
true
Hides this POI when the linked objective is completed. Exception: if this is a discovered Location-category POI, it stays visible even after the objective completes.
Only Show When Active
bool
true
Hides the POI until the linked objective is the currently active step in the quest's sequential progression. Future and past objectives are hidden.
Auto-Link Location
bool
true
On Start, if no objective ID is set, scans active quests for a GoToLocationObjective whose targetPosition is within 5 metres of this marker and links to it automatically.
Show Gizmo
bool
true
Draws the objective link indicator in the Scene view (see Gizmos below).
Gizmo Color
Color
Cyan
Colour of the objective link gizmo. Only shown when Show Gizmo is enabled.
Dialogue Trigger Integration
When a DialogueTrigger on the same (or another) GameObject marks a conversation as completed, this POI can hide itself automatically — useful for quest givers who should no longer show a marker after their opening dialogue has played.
Auto-Detect
bool
true
At runtime, searches this GameObject with GetComponent<DialogueTrigger>() if no manual reference is assigned.
Linked Dialogue Trigger
DialogueTrigger
—
Manual reference to any DialogueTrigger in the scene. Takes precedence over auto-detection.
Hide When Completed
bool
true
Hides this POI when the linked trigger's HasTriggered becomes true, or if it was already completed in the save system when the scene loads.
When a manual reference is set, an info box shows the linked trigger's GameObject name, dialogue asset name, triggerOnce flag, and saveTriggerState setting.
In Play mode the section shows live status: whether the dialogue has been completed and whether the trigger can currently fire.
Save-system awareness — On Start, the POI Marker queries
DialogueSaveSystemdirectly using the same ID generation logic asDialogueTriggerto check completion state. This avoids problems caused by same-frame execution order, where theDialogueTrigger's ownStart()may not yet have run.
World Marker (3D)
An optional 3D prefab spawned in world space above this POI's position.
Marker Prefab
GameObject
—
Prefab instantiated as a child of this GameObject at Start (if the POI is active). If left empty, the POI appears only on 2D navigation surfaces.
Position Offset
Vector3
(0, 2, 0)
Local-space offset applied to the spawned instance. Also defines WorldPosition, which is what the map and elevation systems use for icon placement.
Face Camera
bool
true
Every Update, the world marker rotates to face Camera.main (billboard behaviour).
The world marker is created lazily: if the POI starts inactive, the prefab is not instantiated until the POI is activated. If the POI is a Location with HideUntilDiscovered, the prefab is not instantiated until the location is first discovered.
Events
State Events
On POI Activated
UnityEvent
IsActive changes to true.
On POI Deactivated
UnityEvent
IsActive changes to false.
Distance Events
On Distance Changed
UnityEvent<float>
The cached distance changes by more than 0.1 world units since last check. Passes the new distance.
On Player Enter Range
MEvent
The player crosses into the visible range window (MinDistance–MaxDistance).
On Player Exit Range
MEvent
The player exits the visible range window.
Debug Options
Debug Mode
Enables detailed Debug.Log output for all visibility decisions, registration events, objective evaluations, and location triggers.
Status & Debug Tools
In edit mode, the section validates the configuration:
Error if no POI Data is assigned and Custom Settings is off
Warning if Custom Name or Custom Map Icon is missing when using inline settings
Warning if a quest is selected but no objective has been chosen
Confirmation that auto-register is enabled, or a warning that manual registration is required
In Play mode, the section shows:
IsActive, current distance, name, and categoryLive
ShowOnMinimap,ShowOnCompass,ShowWorldMarkervalues (including discovery-gate results)Quest link status: quest name, objective description, whether the quest is active/completed, whether the objective is in progress or done
Testing buttons (Play mode only):
Activate / Deactivate
Toggles IsActive immediately. Label updates to reflect the current state.
Register
Calls RegisterPOI() manually.
Unregister
Calls UnregisterPOI() manually, which also destroys the world marker instance.
Scene Gizmos
Visible when the GameObject is selected in the Scene view.
Inner wire sphere
Drawn at MinDistance radius, tinted with the POI's icon colour at 30% opacity. Represents the near-clip distance.
Outer wire sphere
Drawn at MaxDistance radius at 10% opacity. Represents the visibility range limit.
Wire cube
Drawn at transform.position + worldMarkerOffset. Shows exactly where the world marker prefab will spawn.
Objective link sphere
Cyan (configurable) 2 m wire sphere and a bold label above the object showing "Objective: [id]". Only shown when Show Gizmo is enabled and an objective ID is set.
Location trigger sphere
Green-cyan wire sphere at TriggerRadius, with a light filled sphere for area context. A bold label above shows the location name and radius. Only shown when Enable Location Trigger is enabled.
The OnSceneGUI handles also draw two stacked horizontal discs and a tall vertical line (10 units high) at the marker's position as a scene-view beacon, coloured with the POI's icon colour.
Visibility Resolution
POI Marker uses a priority chain to determine whether to show each navigation surface. All three (ShowOnMinimap, ShowOnCompass, ShowWorldMarker) apply the same gate order:
POI Data flag —
poiData.ShowOnMinimap(or equivalent) must be true.Discovery gate — If this is a
LocationPOI and bothIsDiscoverableandHideUntilDiscoveredare true, the marker is hidden untilLocationManager.IsDiscovered(locationId)returns true.
Objective Visibility Logic
When a quest and objective are linked and onlyShowWhenObjectiveActive is true, EvaluateObjectiveVisibility() determines IsActive following this precedence:
Inspector isActive was false at Start
Always hidden — designer intent overrides everything.
Dialogue trigger has been completed
Hidden.
Quest not yet started or already completed
Hidden.
Objective completed + hideWhenObjectiveComplete true
Hidden — unless this is a discovered Location POI, in which case it remains visible.
Objective is the current active step in the quest sequence
Shown.
Objective is a future step not yet reached
Hidden.
This evaluation re-runs whenever a relevant QuestEventBus event fires (QuestStarted, QuestCompleted, QuestFailed, QuestProgressUpdated).
Public API
Registration
RegisterPOI()
Manually registers this marker with POIManager. Called automatically in Start when autoRegister is true.
UnregisterPOI()
Removes this marker from POIManager and destroys the world marker instance.
State
IsActive
bool (get/set)
Setting to false hides the world marker and fires OnPOIDeactivated. Setting to true shows it and fires OnPOIActivated.
UpdateDistance()
void
Recalculates CurrentDistance and fires range events. Called by POIManager each update interval for registered markers.
Quest & Objective
EvaluateObjectiveVisibility()
void
Re-evaluates and updates IsActive based on the current quest and objective state. Called automatically when quest events fire; call manually after quest state changes outside the event bus.
SetLinkedObjectiveId(string)
void
Sets the linked objective ID at runtime.
GetLinkedObjectiveData()
QuestObjectiveData
Returns the runtime data for the linked objective from QuestManager, or null if not found.
IsObjectiveTracked()
bool
Returns true if the linked objective's isTracked flag is set in QuestManager.
Location
TriggerLocationDiscovery()
void
Manually marks this location as discovered via LocationManager.DiscoverLocation(). Use for scripted discovery events (cutscenes, loading screens).
IsLocationDiscovered()
bool
Returns LocationManager.IsDiscovered(poiData.LocationId), or false if this is not a Location POI.
IsDiscovered()
bool
Same as IsLocationDiscovered(). Returns true for non-Location POIs (they are always considered "discovered").
Waypoint Conversion
SetAsWaypoint(string name, Sprite icon, Color color)
Switches to Custom Settings mode and configures this marker as a Waypoint-category POI. Used by CustomWaypoint and waypoint creation systems.
Key Properties
POIName
string
Custom name if using custom settings, otherwise poiData.POIName.
MapIcon
Sprite
Custom icon or asset icon.
CompassIcon
Sprite
Custom icon or asset icon.
IconColor
Color
Custom colour or asset colour.
Category
POICategory
Custom category or asset category.
WorldPosition
Vector3
transform.position + worldMarkerOffset. This is what the minimap, world map, compass, and elevation system all use.
CurrentDistance
float
Cached distance to the player, updated at POIManager.updateInterval.
ShowOnMinimap
bool
Final resolved visibility after applying data flags and discovery gates.
ShowOnCompass
bool
Final resolved visibility.
ShowWorldMarker
bool
Final resolved visibility.
IsLocationPOI
bool
True when poiData != null && poiData.IsLocation.
TriggerRadius
float
Active location trigger radius: custom value if overriding, otherwise poiData.LocationRadius.
PlayerInsideLocation
bool
True while the player's collider is inside the location trigger zone.
LinkedDialogueTrigger
DialogueTrigger
The resolved dialogue trigger reference (auto-detected or manually set).
Workflow: Setting Up a New POI Marker
Add the POI Marker component to the scene GameObject you want to track.
Drag a
PointOfInterestasset into the POI Data slot, or enable Use Custom Settings and fill in inline values.If this is a Location POI, click Sync World Position to Asset to write the scene position into the asset.
To link with quest progression, select the Linked Quest asset, then pick the objective from the dropdown.
If the location should trigger discovery when the player walks into it, enable Enable Location Trigger. Use the Add SphereCollider Now editor button if you prefer to see the collider at design time.
Assign a Marker Prefab if you want a 3D billboard above the object in the game world.
Enter Play mode — the icon should appear on the minimap and compass immediately.
Other Tips
WorldPositionincludes the offset — The map icon is placed attransform.position + worldMarkerOffset, not at the raw transform. If icons appear 2 metres above where you expect on the map, the offset is the reason. Set it toVector3.zerofor flat-plane markers.Objective visibility vs. IsActive — Setting
IsActive = falsein the inspector permanently suppresses the marker (theinspectorIsActiveflag captures this at Start). The objective system will never re-enable it. If you want quest logic to control a marker that starts hidden, setisActive = truein the inspector and let the objective visibility logic hide it on first evaluation.Discovery gate is per-surface —
HideUntilDiscoveredhides the minimap and compass icons but the Location Discovery trigger is still active. The player can physically enter the area and discover the location even while the icon is invisible.Auto-Link Location runs once at Start — If no objective ID is set and a matching
GoToLocationObjectiveexists within 5 metres, it links automatically. This saves setup time for densely placed markers but can produce false matches if two objectives are close together. Prefer the Quest Integration dropdown for explicit control.Same-frame execution with DialogueTrigger — The save-system check in
InitializeDialogueTrigger()works around Unity's non-deterministic Start() order. No special script execution order settings are required.Persistent markers across scenes — Mark
isPersistent = trueonly for markers that genuinely need to survive the full game session (e.g. a hub town). Overusing persistence adds overhead and can cause duplicate entries if the same scene is reloaded.
Last updated