Jovian Zone System v0.1.0

A polygon-based zone system for defining map regions with encounter difficulty, modifiers, and safe areas.

Table of Contents

Overview

The Zone System lets you paint polygon regions on your map and assign encounter rules to each region. At runtime, you query a world position and get back a fully resolved ZoneContext with the encounter table, difficulty tier, and chance.

Key Features

Setup & Quick Start

1. Scene Setup

  1. Create a GameObject and add the ZonesObjectHolder component.
  2. Set the Map Plane field to match your map orientation.
Map PlaneUse CaseAxesIgnored
XYFlat sprite map, UI mapX, YZ
XZ3D world map (standard Unity 3D)X, ZY
YZSide-on mapY, ZX

2. Create Your First Zone

  1. Open Window → Zone System → Zone Editor.
  2. Click Create New Zone.
  3. Enter a name, select a shape (Square, Circle, or Polygon).
  4. Click Create & Edit.
  5. Edit zone data fields (role, priority, encounter settings).
  6. Click Save Zone to persist the asset.
  7. Use Scene view handles to adjust the polygon shape.
Note: The zone asset is not saved to disk until you click the Save button. You can edit all fields freely before committing.

Zone Editor Window

The Zone Editor window (Window → Zone System → Zone Editor) is the primary tool for managing zones.

Zone List View

Shows all ZoneInstance objects in the current scene. Each row displays:

Zones with missing ZoneData show a warning icon with options to add data or delete the zone.

Create Zone

Click Create New Zone to open the creation dropdown:

The zone is created in-memory and enters edit mode immediately. You must click Save to persist the asset.

Edit Mode

When editing a zone, all ZoneData fields are available inline:

Save Validation

On save, the editor checks for:

If a conflict is found, an error is displayed and saving is blocked.

Auto-applied Changes on Save

Export Section

At the bottom of the editor window, expand Export Zones to JSON to export all scene zones to a JSON file for runtime loading.

Shape Editing

When a zone is in edit mode, yellow handles appear in the Scene view for each polygon vertex.

Controls

ActionInputDescription
Move vertexDrag handleDrag any yellow handle to reposition a vertex
Insert vertexCtrl + Click edgeAdds a new vertex on the closest edge (cyan highlight shows target)
Delete vertexShift + Click vertexRemoves the vertex (minimum 3 vertices). Handles turn red while Shift is held.
Stop editingEscExits shape edit mode

Shapes

ShapeDefaultNotes
Square4 vertices, 2-unit half-sizeCan be reshaped into any quad
Circle24-segment approximation, radius 2Drag the radius handle to resize. Regenerates vertices on radius change.
Polygon12 vertices, radius 3Fully freeform — add, remove, and drag vertices freely

Additional Tools (Inspector)

Scene interaction: While in shape edit mode, clicking in the Scene view will not select other objects. The default transform handle is hidden to prevent accidental movement.

Zone Roles & Resolution

Roles

RolePurposeFields
Base Defines the encounter table and baseline difficulty Encounter Table ID, Difficulty Tier, Encounter Chance
Modifier Stacks multiplicatively on top of a Base zone Chance Multiplier, Difficulty Tier Bonus
Override Replaces everything — towns, story events, safe areas Is Safe Zone, Encounter Table ID, Encounter Chance, Difficulty Tier

Resolution Order

When querying a world position, the ZoneResolver follows this order:

  1. If any Override zone is present → use the highest-priority Override exclusively
  2. Find the highest-priority Base zone → encounter table + baseline difficulty
  3. Stack all Modifier zones multiplicatively on top
  4. Clamp and return a ZoneContext

Modifier Stacking

Modifiers are multiplicative, so each one is independent:

Base chance 0.30  x  Cursed Road 1.8  x  Night Modifier 1.2  =  0.648

Priority

Higher priority values take precedence. When multiple zones of the same role overlap, the highest-priority one wins (for Base and Override) or all are stacked (for Modifier).

Editor Settings

Access via Window → Zone System → Settings. If no settings asset exists, one is created automatically.

Fields

FieldDescriptionDefault
mapPlaneWhich two world axes your map lies onXZ
zoneDataFolderFolder path where new ZoneData assets are savedAssets/ZoneData
roleColorsDebug color for each zone role (used in scene rendering)Blue (Base), Yellow (Modifier), Green (Override)

Role Colors

Each ZoneRole has a configurable color in the settings. When you change a zone’s role in the editor, its debug color is automatically updated to match. Colors are used for:

Dynamic: If you add new values to the ZoneRole enum, call SyncRoleEntries() on the settings asset or click the settings menu item — missing roles will be added with a default gray color.

Runtime API

ZoneSystemApi

The main entry point for runtime zone queries.

// Create the API with a reference to the ZonesObjectHolder
ZoneSystemApi api = new ZoneSystemApi(zonesObjectHolder);

// Full zone resolution at a world position
ZoneContext ctx = api.QueryZone(partyWorldPosition);

if(!ctx.isSafe && Random.value < ctx.finalEncounterChance)
    TriggerEncounter(ctx.encounterTableId, ctx.finalDifficultyTier);

Methods

MethodReturnsDescription
QueryZone(Vector3)ZoneContextFull resolution: finds overlapping zones, applies modifiers, returns final context
GetOverlappingZones(Vector3)List<ZoneData>Raw list of all zones containing the position, sorted by descending priority
IsInSafeZone(Vector3)boolQuick check — true if any Override zone with isSafeZone contains the position
Register(ZoneInstance)voidRegister a dynamically spawned zone
Unregister(ZoneInstance)voidUnregister a zone before destroying it

ZoneContext Struct

FieldTypeDescription
encounterTableIdstringID of the encounter table to use
finalEncounterChancefloatFinal encounter probability (0–1), after modifier stacking
finalDifficultyTierDifficultyTierFinal difficulty tier, after modifier bonuses
isSafeboolTrue if in a safe zone (no encounters)
resolvedZoneNamestringName of the zone that “won” resolution (for debug/UI)

Dynamic Zones

// After instantiating a zone at runtime:
api.Register(zoneInstance);

// Before destroying:
api.Unregister(zoneInstance);

Type Reference

Enums

ZoneRole

ValueDescription
BaseProvides the encounter table and baseline difficulty
ModifierMutates difficulty/chance on top of a Base zone
OverrideCompletely replaces everything (safe towns, story events)

ZoneShape

ValueDescription
Square4-vertex quadrilateral
Circle24-segment circular approximation with adjustable radius
PolygonFreeform polygon with 12 default vertices

DifficultyTier

ValueInt
Safe0
Mild1
Moderate2
Dangerous3
Deadly4

MapPlane

ValueAxesDepth
XYX, YZ
XZX, ZY
YZY, ZX

ScriptableObjects

ZoneData

Per-zone configuration asset. Created via the Zone Editor or Create → ZoneSystem → Zone Data.

FieldTypeDescription
zoneIdstringUnique identifier
zoneNamestringDisplay name
roleZoneRoleBase, Modifier, or Override
priorityintHigher wins in same-role conflicts
debugColorColorScene visualization color (auto-set from role)
shapeZoneShapeShape type
circleRadiusfloatRadius (Circle shape only)
polygonList<Vector2>Vertex positions (local to transform)

MonoBehaviours

ZoneInstance

Placed on a scene GameObject. References a ZoneData asset and provides spatial queries.

Field / MethodDescription
dataReference to the ZoneData asset
Contains(Vector3, MapPlane)Returns true if the world position is inside this zone
RebuildBoundsCache()Recalculates the AABB cache (call after modifying polygon)

ZonesObjectHolder

Scene manager that holds the map plane setting and provides access to all zones.

Field / PropertyDescription
mapPlaneWhich plane the map lies on (XY, XZ, or YZ)
AllZonesRead-only list of all ZoneInstance objects in the scene

Utility Classes

PolygonUtils

Static math utilities for polygon operations.

MethodDescription
PointInPolygon(Vector2, List<Vector2>)Ray-casting point-in-polygon test (Jordan curve theorem)
PointInPolygon(Vector3, List<Vector2>, MapPlane)Projects world position to plane, then tests
Centroid(List<Vector2>)Average center of polygon vertices
Bounds(List<Vector2>)Axis-aligned bounding box (min, max)
PointInBounds(Vector2, Vector2, Vector2)Fast AABB pre-check
Triangulate(List<Vector2>)Ear-clipping triangulation for concave polygon rendering

MapPlaneUtility

Converts between 3D world positions and 2D plane coordinates.

MethodDescription
ProjectToPlane(Vector3, MapPlane)3D world → 2D plane coordinates
UnprojectFromPlane(Vector2, MapPlane, float)2D plane coordinates → 3D world

ShapeFactory

Generates default polygon vertices for each shape type.

MethodDescription
CreateDefault(ZoneShape)Returns default vertices for the given shape
CreateSquare(float)4-vertex square with given half-size
CreateCircle(float, int)N-segment circle approximation
CreatePolygon(float, int)Regular polygon with N vertices
RegenerateCircle(ZoneData)Rebuilds circle vertices from current radius

ZoneResolver

Pure logic for resolving overlapping zones into a single ZoneContext.

MethodDescription
Resolve(List<ZoneData>)Takes overlapping zone data, applies role priority and modifier stacking, returns ZoneContext

ZoneExporter

Serializes scene zones to a JSON structure for runtime loading.

MethodDescription
BuildExport(ZoneInstance[], MapPlane)Builds the export data structure from scene instances
ToJson(ZoneExportRoot, bool)Converts to JSON string (optionally pretty-printed)

JSON Export

In the Zone Editor window, expand Export Zones to JSON, set the output path, and click Export Now.

Loading at Runtime

string json = File.ReadAllText(Application.streamingAssetsPath + "/zones.json");
ZoneExportRoot root = JsonUtility.FromJson<ZoneExportRoot>(json);

Export Structure

Each zone is exported as a ZoneExportEntry containing all zone data fields plus the world-space polygon coordinates and transform position.

Keyboard Shortcuts

KeyContextAction
EscScene view, shape editing activeStop editing the zone shape
Ctrl + ClickScene view, shape editing activeInsert a vertex on the nearest edge
Shift + ClickScene view, shape editing activeDelete the clicked vertex (min 3)
Menu PathDescription
Window → Zone System → Zone EditorOpens the main Zone Editor window
Window → Zone System → SettingsSelects (or creates) the ZoneEditorSettings asset
Window → Zone System → DocumentationOpens this documentation in your default browser
Jovian → ZoneSystem → Zone Editor SettingsCreate menu for new ZoneEditorSettings asset
ZoneSystem → Zone DataCreate menu for new ZoneData asset

Jovian Zone System v0.1.0 — com.jovian.zonesystem