How to create a minimap for VR in Unity

A short Unity walkthrough for building a VR minimap in ToledoVR.

View the original post
How to create a minimap for VR in Unity

A short clip of the ToledoVR minimap in use.

1. Create the minimap model from Terrain

Use the following script to create a model from the terrain:

TerrainObjExporter (archived Unity wiki). A maintained copy lives on GitHub.

2. Add the Model to your Scene

3. Create the Texture for your Model

Use an orthographic camera to take a picture of your terrain.

Use print screen to save the image.

4. Create the Material

Create a new Material and add the picture in step 3. Add this material to all the Meshes of your Minimap.

5. Add the Script

Adding this script and setting the appropriate values in the Inspector will make an object on the minimap mirror the movement of the corresponding object.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MiniMap : MonoBehaviour
{

    public Transform trackedObject;
    public Transform miniMapObject;
    public Transform baseOrig;
    public Transform boundOrigX;
    public Transform boundOrigZ;
    public Transform boundMiniX;
    public Transform boundMiniZ;
    public float lengthXOriginal;
    public float lengthYOriginal;
    public float lengthZOriginal;
    public float lengthXMiniMap;
    public float lengthYMiniMap;
    public float lengthZMiniMap;

    private float ratioX;
    private float ratioY;
    private float ratioZ;

    public GameObject dynamicObject;

    void Start()
    {
        lengthXOriginal = Vector3.Distance(baseOrig.position, boundOrigX.position);
        lengthZOriginal = Vector3.Distance(baseOrig.position, boundOrigZ.position);
        lengthXMiniMap = Vector3.Distance(transform.position, boundMiniX.position);
        lengthZMiniMap = Vector3.Distance(transform.position, boundMiniZ.position);
        ratioX = (lengthXMiniMap / lengthXOriginal);
        ratioY = (lengthYMiniMap / lengthYOriginal);
        ratioZ = (lengthZMiniMap / lengthZOriginal);
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 positionGod = trackedObject.position - baseOrig.position;
        Vector3 newPositionGod = new Vector3();
        newPositionGod.x = ratioX * positionGod.x;
        newPositionGod.y = ratioY * positionGod.y;
        newPositionGod.z = ratioZ * positionGod.z;
        miniMapObject.localPosition = newPositionGod;
    }

    public void AddDynamicObject(Transform transform)
    {
        GameObject go = Instantiate(dynamicObject, this.transform);
        MiniMapEnemy miniMapEnemy = go.GetComponent<MiniMapEnemy>();
        miniMapEnemy.Initialize(baseOrig,transform,ratioX,ratioY,ratioZ);

    }

}

Add this script to objects that are created dynamically.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MiniMapEnemy : MonoBehaviour
{
    private Transform myTransform;

    public Transform pivot;
    public Transform master;
    public float ratioX;
    public float ratioY;
    public float ratioZ;
    private bool inizialized;

    void Start()
    {
        myTransform = transform;
    }

    public void Initialize(Transform pivot, Transform master, float ratioX, float ratioY, float ratioZ)
    {
        this.pivot = pivot;
        this.master = master;
        this.ratioX = ratioX;
        this.ratioY = ratioY;
        this.ratioZ = ratioZ;
        inizialized = true;
    }

    // Update is called once per frame
    void Update()
    {
        if (!inizialized)
        {
            return;
        }
        if (master != null)
        {
            Vector3 position = master.position - pivot.position;
            Vector3 newPosition = new Vector3();
            newPosition.x = ratioX * position.x;
            newPosition.y = ratioY * position.y;
            newPosition.z = ratioZ * position.z;
            myTransform.localPosition = newPosition;
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

6. Make the Minimap Interactable

Use VRTK’s Interactable Object to make your minimap grabbable.

Back to the archive Open on somedudes.ch
Beaver Wars: a 15-second progress trailer

September 14, 2026

Beaver Wars: a 15-second progress trailer

Astra rebuilt the River Crossing world from a ChatGPT Images 2.5 plate. A 15-second clip of the turns it took.

Read more
Beaver Wars: a development history

August 25, 2026

Beaver Wars: a development history

Beaver Wars screenshots from April 26 through September 14, 2026.

Read more
The glory of VR slowmotion

February 20, 2017

The glory of VR slowmotion

A look at ToledoVR combat when slow motion kicks in.

Read more