> For the complete documentation index, see [llms.txt](https://malbersanimations.gitbook.io/animal-controller/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://malbersanimations.gitbook.io/animal-controller/malbers-questforge/world-map/fog-of-war.md).

# Fog of War

### Overview

**WorldMapFogOfWar** is an optional overlay component that covers unexplored areas of the world map with a translucent fog, which is peeled back as the player discovers named locations and physically explores the world.

> Add via **Component menu: `Malbers Quest Forge → World Map Fog of War`**\
> Assign the component to the **Fog of War Component** slot on **WorldMapUI**.

***

<figure><img src="https://963537199-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Lzhr1XSMzMqNXjRnNlb%2Fuploads%2FmACmToGcy8XY3e0KWZrk%2Fimage.png?alt=media&amp;token=781b8c1f-0b89-47cf-95d7-e254d4494964" alt=""><figcaption></figcaption></figure>

### How It Works

The fog is rendered as a CPU-generated `Texture2D` applied to a `RawImage` that sits over the map. The texture is an alpha mask: fully opaque pixels show the configured fog colour; fully transparent pixels let the map show through. The entire texture is rebuilt from scratch each time conditions change — there is no incremental update.

**Rebuild steps, in order:**

1. Fill every pixel of the `alphaMap` to `1.0` (fully fogged).
2. **Carve discovered locations** — for each location ID in `LocationManager.GetDiscoveredLocationIds()`, find the matching POI world position and carve a reveal circle.
3. **Carve exploration breadcrumbs** — carve a smaller reveal circle at every breadcrumb position the player has visited.
4. **Carve player position** — carve the real-time circle around the player's current XZ position.
5. Convert the `alphaMap` to `Color32` pixels: RGB = `fogColor`, alpha = `alphaMap[i] * fogColor.a`.
6. Upload to GPU via `SetPixels32` + `Apply`.

For overlapping circles, the **minimum** alpha value wins — a pixel can only ever be made more revealed, never less.

**Gradient edge:** When `useGradientReveal` is `true` and `edgeSoftness > 0`, pixels between `pixelRadius` and `pixelRadius + softness` are linearly interpolated from fully revealed to fully fogged, producing a soft feathered edge instead of a hard cut-off.

**Rebuild timing:** `LateUpdate` triggers a rebuild only when the map is open and `isDirty = true`. The `isDirty` flag is set by: player moving more than 5 units (when **Reveal Around Player** is on), a new location being discovered, or a new breadcrumb being dropped. Breadcrumb tracking itself runs in `Update` regardless of whether the map is open.

***

### Properties

**Fog of War Settings**

| Property              | Type  | Default          | Description                                                                                                                        |
| --------------------- | ----- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| **Enable Fog of War** | Bool  | `true`           | Master toggle. When `false`, `IsAreaRevealed()` always returns `true` and the overlay is hidden.                                   |
| **Fog Color**         | Color | Black, 85% alpha | RGB sets the fog tint; alpha sets the maximum opacity. A pixel inside a fully fogged area is drawn at this exact colour and alpha. |
| **Reveal Radius**     | Float | `100`            | World-unit radius carved around each **discovered location**.                                                                      |
| **Edge Softness**     | Float | `20`             | Width of the gradient transition zone at circle edges. `0` = hard edge.                                                            |

**Rendering**

| Property               | Type       | Default  | Description                                                                                                                                                                          |
| ---------------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Fog Overlay Image**  | `RawImage` | Required | The UI `RawImage` that displays the fog texture. Must be layered over the map in the Canvas hierarchy. Its colour is forced to pure white at runtime so it doesn't tint the texture. |
| **Texture Resolution** | Int        | `512`    | Width and height of the fog `Texture2D` in pixels. A `512×512` texture uses \~1 MB of CPU memory. Higher values give sharper circle edges at the cost of longer rebuild times.       |
| **Gradient Reveal**    | Bool       | `true`   | Enables the soft feathered edge. When `false`, reveals have a hard pixel boundary.                                                                                                   |

**Real-time Reveal**

| Property                 | Type  | Default | Description                                                                                                                                                                    |
| ------------------------ | ----- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Reveal Around Player** | Bool  | `true`  | Continuously reveals a circle around the player's current position. The circle moves as the player moves, but only triggers a rebuild when the player moves more than 5 units. |
| **Player Reveal Radius** | Float | `50`    | World-unit radius of the real-time player reveal circle.                                                                                                                       |

**Exploration Breadcrumbs**

| Property                        | Type  | Default | Description                                                                                                                                                    |
| ------------------------------- | ----- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Enable Exploration Tracking** | Bool  | `true`  | Records the player's path as a list of world positions and permanently reveals areas around each point. Tracking runs in `Update` even when the map is closed. |
| **Drop Distance**               | Float | `10`    | World units the player must travel (XZ only) before a new breadcrumb is placed. Smaller values = smoother reveal trail, more breadcrumbs stored.               |
| **Breadcrumb Reveal Radius**    | Float | `40`    | World-unit radius carved around each breadcrumb position. Generally smaller than **Reveal Radius** as breadcrumbs represent a path, not a named location.      |
| **Max Breadcrumbs**             | Int   | `0`     | Hard cap on stored breadcrumbs. When the cap is reached, the oldest breadcrumb is removed before adding a new one, creating a sliding window. `0` = unlimited. |

***

### POI Visibility Rules

When the WorldMapUI evaluates whether to display a POI icon, it calls `IsAreaRevealed(worldPos)`. The check follows this order:

1. If fog is disabled → **always visible**.
2. If the POI is within **Player Reveal Radius** → **visible**.
3. If the POI is within **Reveal Radius** of any discovered location → **visible**.
4. If within **Breadcrumb Reveal Radius** of any breadcrumb → **visible**.
5. Otherwise → **hidden**.

**Two POI types always bypass this check entirely**, regardless of fog state:

* `CustomWaypoint` — the player placed it intentionally.
* `POIMarker` with a `linkedObjectiveId` — active quest objective markers always show.

***

### Save & Load

Breadcrumbs can be persisted across sessions via the save system:

| Method                           | Description                                                                                                                                                      |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ExplorationBreadcrumbs`         | `IReadOnlyList<Vector3>` — read-only access to all current breadcrumbs. Serialize this for saving.                                                               |
| `LoadBreadcrumbs(List<Vector3>)` | Replaces the breadcrumb list with saved data and sets `isDirty = true`. Sets `lastBreadcrumbPosition` to the final entry to prevent an immediate duplicate drop. |

Discovered location reveals are driven by `LocationManager` — those are saved separately by the location system and do not need to be handled here.

***

### Public API

| Method                           | Description                                                                                                                           |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `Initialize(WorldMapUI)`         | Called automatically by `WorldMapUI.OpenMap()`. Subscribes to `LocationManager.OnLocationDiscovered` and triggers an initial rebuild. |
| `IsAreaRevealed(Vector3)`        | Returns `true` if the given world position falls within any revealed area. Used by WorldMapUI's icon display loop.                    |
| `SetEnabled(bool)`               | Enables or disables the fog overlay at runtime.                                                                                       |
| `ForceRebuild()`                 | Sets `isDirty = true` and immediately rebuilds the texture if the map is open.                                                        |
| `RevealAll()`                    | Hides the fog overlay `GameObject` entirely. Does not clear breadcrumb or location data.                                              |
| `ResetFog()`                     | Clears all breadcrumbs, resets `isDirty`, and rebuilds — returning the map to its fully fogged initial state.                         |
| `ClearBreadcrumbs()`             | Removes all exploration breadcrumbs without touching discovered location reveals. Triggers a rebuild.                                 |
| `LoadBreadcrumbs(List<Vector3>)` | Restores breadcrumbs from saved data.                                                                                                 |
| `BreadcrumbCount`                | `int` — number of breadcrumbs currently stored. Shown live in the Inspector during Play Mode.                                         |

***

### Inspector Testing Tools *(Play Mode Only)*

| Button                | Action                                                                             |
| --------------------- | ---------------------------------------------------------------------------------- |
| **Force Rebuild**     | Calls `ForceRebuild()`.                                                            |
| **Reveal All**        | Calls `RevealAll()` — hides the overlay.                                           |
| **Reset Fog**         | Calls `ResetFog()` — clears everything and rebuilds fully fogged.                  |
| **Clear Breadcrumbs** | Calls `ClearBreadcrumbs()`. Only shown when **Enable Exploration Tracking** is on. |

***

### Setup Checklist (IF NOT USING ONE-CLICK SETUP!)

* [ ] &#x20;Add **WorldMapFogOfWar** as a component somewhere in the WorldMapUI hierarchy.
* [ ] &#x20;Create a `RawImage` UI element layered over the `MapContent` in the Canvas and assign it to **Fog Overlay Image**. It should match the map's rect exactly.
* [ ] &#x20;Assign the component to the **Fog of War Component** slot on **WorldMapUI**.
* [ ] &#x20;Set **Reveal Radius** to match the typical size of your named areas in world units.
* [ ] &#x20;Set **Edge Softness** to 15–25% of **Reveal Radius** for a natural-looking fade.
* [ ] &#x20;If your world is large and performance is a concern, test with `256` texture resolution before increasing.
