Skip to content

Cookbook

Copy-paste recipes.

Green = written. Open a chapter, then a recipe. Back works.

Move, tilt, and limit the view.

Where tiles come from, including your own server.

Lines, shapes, and real-world metres.

Extra imagery on top of the base map.

How many tiles stay in graphics memory.

Sharpness versus bandwidth.

Place names and your own text.

Pins, prefabs, clusters, clicks.

Nothing matches. Clear the search to see all 8 chapters.
01Follow a moving objectGPS / sim

Adds a blue dot. Follow Position keeps the map on the device (or a simulated walk in the editor).

C#
var follow = gameObject.AddComponent<LocationFollowController>();
follow.Map = Map;
follow.FollowPosition = true;
follow.RotateWithHeading = false;
03Zoom to a markerFlyTo

Moves center and zoom together. Duration is seconds. Leave zoom out to keep the current level.

C#
Map.FlyTo(48.8584, 2.2945, zoom: 16, durationSeconds: 0.8);
04Smooth pan to a coordinateFlyTo

Same call, no zoom argument - only the center eases. CancelFly if the user grabs the map.

C#
Map.FlyTo(51.5074, -0.1278, durationSeconds: 0.4);
// Map.CancelFly();
05Limit how far out you can zoominput

These live on MapInteractionController, not the view. They clamp the user, not a script that sets Map.Zoom.

C#
var input = GetComponent<MapInteractionController>();
input.MinZoom = 5;
input.MaxZoom = 18;
06Tilt and rotate the viewview state

Pitch maxes out at 60 degrees so the horizon stays off-screen. Rotation is counterclockwise, 0 = north up.

C#
Map.PitchDeg = 45;
Map.RotationDeg = 30;
09Snap back to northview state

North is rotation 0. Assign it. There is no separate reset call.

C#
Map.RotationDeg = 0;
11Two-finger zoom on a phonetouch

Pinch, twist and two-finger pitch are on when you add MapInteractionController. These flags turn pieces off.

C#
var input = GetComponent<MapInteractionController>();
input.TouchEnabled = true;
input.MouseEnabled = true;
input.MaxPitchDeg = 60;
14Restore the last camera positionview state

The view is five numbers. Save them, write them back.

C#
PlayerPrefs.SetString("map-view",
  Map.Latitude + "," + Map.Longitude + "," + Map.Zoom
  + "," + Map.RotationDeg + "," + Map.PitchDeg);
01Use your own tilescustom

Any {z}/{x}/{y} template. Put the API key in as {key}, not in the URL - an inline key poisons the disk cache.

C#
Map.Provider = TileProvider.Custom;
Map.CustomUrlTemplate = "https://tiles.example.com/{z}/{x}/{y}.png?key={key}";
Map.ApiKey = "YOUR_KEY";
Map.CustomAttribution = "(c) Example Tiles";
Map.CustomTileSizePx = 256;
02Switch provider while runningSetProvider

Rebuilds the tile pipeline. Markers, labels and drawings stay. Each template has its own disk cache, so you will not see the old provider's tiles.

C#
Map.SetProvider(TileProvider.MapTiler, style: "streets-v2",
  apiKey: "YOUR_KEY", retina512: true);
03Add an API keyinspector or code

One field. Placeholder is {key}. Setting ApiKey after Start does nothing until the next SetProvider.

C#
Map.ApiKey = "YOUR_KEY";
Map.SetProvider(Map.Provider, Map.ProviderStyle, Map.ApiKey);
05Cache tiles on diskdefault on

Platform Default sizes the cache for the machine (up to 10 GB desktop, 2 GB phone). Manual uses the megabytes you type.

C#
Map.CacheSizeMode = DiskCacheSizeMode.Manual;
Map.DiskCacheMB = 512;
12Ask for 2x (retina) tiles512 px

Sharper, fewer requests, if the provider actually serves 512 px tiles. Ignored on 256-only providers.

C#
Map.Retina512Tiles = true;
01Draw lines and shapeslines

Width is screen pixels. Color32 helpers live in LansMap.Markers.Bulk. At least two points.

C#
Map.Polylines.Store.AddPolyline(new[] {
  new LatLon(48.8584, 2.2945),
  new LatLon(48.8606, 2.3376)
}, widthPx: 4, color: new Color32(255, 80, 80, 255));
10Draw a circle in real metrespolygon ring

No circle primitive. Walk a ring with GeoUtils.DestinationPoint and fill it. Holes are not an API yet.

C#
var center = new LatLon(48.8584, 2.2945);
var ring = new LatLon[32];
for (int i = 0; i < ring.Length; i++)
  ring[i] = GeoUtils.DestinationPoint(center, 400, i * (360.0 / ring.Length));
Map.Polygons.Store.AddPolygon(ring, new Color32(32, 160, 255, 90));
01Add your own tile layeroverlay

A second tile source over the base (hillshade, traffic, a private grid). Set this before Play. OverlayEnabled is read when the pipeline is built.

C#
Map.OverlayEnabled = true;
Map.OverlayProvider = TileProvider.OpenTopoMap;
Map.OverlayOpacity = 0.45f;
06Toggle layers while runningopacity

OverlayEnabled is not a live switch. OverlayOpacity is: 0 hides it, the old value shows it again, with no rebuild.

C#
Map.OverlayOpacity = Map.OverlayOpacity > 0 ? 0f : 0.45f;
10Set opacity per layer0-1

The overlay is the second layer. The base map has no opacity of its own.

C#
Map.OverlayOpacity = 0.3f;
01See how much the map is holdingdebug panel

Tiles downloaded, served from disk, and in graphics memory. Off by default - debug, not for end users.

C#
Map.TileCounterDebugPanelEnabled = true;
02Let Automatic size the tile arraydefault

Automatic (the default) picks how many tiles stay in graphics memory from the screen, max tilt, and GPU memory. Leave it. Use Manual plus LayerCount only after you have measured that you must.

C#
Map.CapacityMode = TileCapacityMode.Automatic;
// Manual override, only after you have measured a need:
// Map.CapacityMode = TileCapacityMode.Manual;
// Map.LayerCount = 256;
04Cap the disk cachemegabytes

Same fields as "Cache tiles on disk". The cap is what the index will serve. Evicted files stay until a rewrite.

C#
Map.CacheSizeMode = DiskCacheSizeMode.Manual;
Map.DiskCacheMB = 256;
Map.OverlayCacheMB = 64;
05Use compressed tile formatscompressed

First codec this device supports wins. Work happens off the main thread. Empty list means uncompressed RGBA32.

C#
Map.TileCompressionPreference = new List<string> {
  "astc4x4", "etc2", "bc1" };
01Pick a tile resolution256 / 512

Presets that serve 512 px honor Retina512Tiles. A custom URL uses CustomTileSizePx of 256 or 512, matching the server.

C#
Map.Retina512Tiles = true;
Map.CustomTileSizePx = 512;
02Sharpen tiles with mipmap biasmips

There is no mip-bias slider. TileMipsEnabled builds a mip chain and uses trilinear. Off by default: about +33% tile-array memory. Set it before Play, or call SetProvider after a flip.

C#
Map.TileMipsEnabled = true;
06Cross-fade instead of poppingdefault on

0.2 seconds on every load is the default. 0 makes every switch instant. Both can change while running.

C#
Map.TileFadeSeconds = 0.2;
Map.FadeAllLoads = true;
01Show place names from the providerOpenFreeMap

Upright place names over whatever raster base you picked. Set BaseMapLabels to false if the tiles already have names and you do not want them twice.

C#
Map.PlaceLabelsEnabled = true;
Map.BaseMapLabels = false;
02Add your own labelsmarker labels

A label hangs off a marker id, not a free coordinate. Add the marker first, then name it.

C#
int id = Map.Markers.Store.Add(
  new LatLon(48.8584, 2.2945), 0, 14f,
  MarkerSizeMode.SceneSize, new Color32(255, 64, 64, 255));
Map.Labels.SetLabel(id, "Eiffel Tower");
04Keep labels upright when the map rotatesupright

Place names and marker labels stay upright. Names baked into the tiles rotate with the map - turn those off with BaseMapLabels.

C#
Map.PlaceLabelsEnabled = true;
Map.BaseMapLabels = false;
01Add a markerpin

One pin at a coordinate. See "Scale a marker with zoom" for constant-on-screen vs metres-on-the-ground.

C#
Map.Markers.Store.Add(
  new LatLon(48.8584, 2.2945), 0, 14f,
  MarkerSizeMode.SceneSize,
  new Color32(255, 64, 64, 255));
02Put a 3D object on the mapprefab

A prefab at a coordinate, real-world scale. The handle stays on the map as the view moves.

C#
WorldMarkerInstance pin = worldMarkerManager.Spawn(pinPrefab,
  45.4642, 9.1900, altitudeMeters: 0);
03Cluster thousands of markersclusters

Nearby markers collapse into one while zoomed out, then split on the way in. Options: getting-started page.

C#
var cluster = gameObject.AddComponent<MarkerClusterController>();
cluster.Map = Map;
cluster.MaxClusterZoom = 13;
04Scale a marker with zoomsize mode

SceneSize is a constant size on screen (a pin). RealSize is metres on the ground, so it shrinks as you zoom out.

C#
Map.Markers.Store.Add(
  new LatLon(48.8584, 2.2945), 0, 40f,
  MarkerSizeMode.RealSize,
  new Color32(255, 64, 64, 255));
05Click and hover on a markerpick

MarkerHoverLabel is the built-in tooltip. For your own click, pick against the current view. You get a slot, not a handle.

C#
gameObject.AddComponent<MarkerHoverLabel>().Map = Map;

if (Input.GetMouseButtonDown(0)) { var sp = new ScreenPoint(Input.mousePosition.x, Input.mousePosition.y); if (Map.Markers.TryPick(Map.CurrentView, sp, 16, out int slot)) Debug.Log(“hit slot “ + slot); }

06Animate a marker movingUpdatePosition

Keep the id from Add and write a new coordinate each frame. Same slot. Nothing spawned or destroyed.

C#
int id = Map.Markers.Store.Add(
  start, 0, 14f, MarkerSizeMode.SceneSize,
  new Color32(255, 64, 64, 255));

Map.Markers.Store.UpdatePosition(id, next, altitudeMeters: 0);

07Give a marker a billboard labelSetLabel

Same as "Add your own labels". The text stays upright as the map rotates.

C#
Map.Labels.SetLabel(id, "Depot 12");
13Filter which markers showzoom range

minZoom and maxZoom are on the packed-color Add, not the Color32 one. Size 0 also hides a live marker without removing it.

C#
Map.Markers.Store.Add(
  new LatLon(48.8584, 2.2945), 0, 14f,
  MarkerSizeMode.SceneSize, 0xFF4040FFu,
  MarkerShape.Circle, false, minZoom: 12f, maxZoom: 18f);
17Change a marker after adding itMarkerHandle

Add returns a MarkerHandle - keep it and mutate the marker directly, instead of tracking the id yourself and calling back into the store.

C#
MarkerHandle pin = Map.Markers.Store.Add(
  new LatLon(48.8584, 2.2945), 0, 14f,
  MarkerSizeMode.SceneSize, 0xFF4040FFu);

// later, once the caller decides this marker is selected pin.OutlineRgba = 0xFFFFFFFFu; pin.ShowStem = true;

No live preview for this view. Code above is real; open a recipe with a live preview to see it running here.
Cookbookhome
Chapters