Welcome to the Unity portion of the geospatial data visualization tutorial! Make sure that you have completed the Data Gathering, Cleaning and Conversion portion first.
Open up Unity, and create a new project.
Click GameObject->Create Empty. Name it "Manager". On the right side, under Components select Add Components and select New Script. Name it ReadCSV. Paste the following code there:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ReadCSV : MonoBehaviour
{
public Transform prefab;
void Awake() {
List<Dictionary<string,object>> data = CSVReader.Read("csv_data");
// fall,geolocation,id,mass,name,nametype,recclass,reclat,reclong,year,X,Y,Z
for(var i=0; i < data.Count; i++) {
Instantiate(prefab, new Vector3((float)data[i]["X"],(float)data[i]["Y"],(float)data[i]["Z"]), Quaternion.identity);
}
}
// public TextAsset t;
// Start is called before the first frame update
void Start()
{
// var result = new JavaScriptSerializer().Deserialize<List<Meteoroid>>(t.text);
// Debug.Log(result);
}
// Update is called once per frame
void Update()
{
}
}
We'll need a few things before we can visualize the data. First, a rudimentary csv parser, since Unity doesn't have one builtin. Luckily there are quite a few open source ones online. Create a new script and name it CSVReader.cs.
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class CSVReader
{
static string SPLIT_RE = @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))";
static string LINE_SPLIT_RE = @"\r\n|\n\r|\n|\r";
static char[] TRIM_CHARS = { '\"' };
public static List<Dictionary<string, object>> Read(string file)
{
var list = new List<Dictionary<string, object>>();
TextAsset data = Resources.Load (file) as TextAsset;
Debug.Log(file);
var lines = Regex.Split (data.text, LINE_SPLIT_RE);
if(lines.Length <= 1) return list;
var header = Regex.Split(lines[0], SPLIT_RE);
for(var i=1; i < lines.Length; i++) {
var values = Regex.Split(lines[i], SPLIT_RE);
if(values.Length == 0 ||values[0] == "") continue;
var entry = new Dictionary<string, object>();
for(var j=0; j < header.Length && j < values.Length; j++ ) {
string value = values[j];
value = value.TrimStart(TRIM_CHARS).TrimEnd(TRIM_CHARS).Replace("\\", "");
object finalvalue = value;
int n;
float f;
if(int.TryParse(value, out n)) {
finalvalue = n;
} else if (float.TryParse(value, out f)) {
finalvalue = f;
}
entry[header[j]] = finalvalue;
}
list.Add (entry);
}
return list;
}
}
The next step is creating the sphere that we'll be using to represent meteorites. Click GameObject->3D Object->Sphere. Drag it down to the Assets section to create a prefab out of it.
We want to tell our Manager that this is the prefab it should use when instantiating the points. To do this, select the Manager in the hierarchy and drag the newly created prefab to the "Prefab" field in the script (ReadCSV) component.
Finally, we want to add the csv_file so that Unity can find it. To do this, create a folder named Resources, and import the csv_file.csv in it.
We are ready! Click the Play button, and wait for Unity to create all the points (can take ~20 seconds on slower machines).
To make the experience more interesting, we can make the camera rotate around the globe. To do this, attach a new script to MainCamera. Name it Rotate Camera. Paste the following code, which takes a center point and make the camera go around it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateCameraScript : MonoBehaviour
{
public Transform target;
public float speed = 3;
// Start is called before the first frame update
void Start()
{
}
void Update(){
transform.LookAt(target);
transform.Translate(Vector3.right * Time.deltaTime * speed);
}
}
Now drag the manager to the target field of the script, and set the speed to something low (I use 3). Enjoy the show!
**Importing Transit Data into Unity for AR/VR**
This tutorial extends the geospatial walkthrough by showing how to bring real‑world transit networks into your Unity project. Transit data often comes from GTFS feeds or APIs (such as the MBTA v3 API) and must be parsed, converted and instantiated as geometry in the scene.
1. **Acquire and prepare your data** – Download the GTFS or API datasets for routes, stops and shapes. Convert latitude/longitude coordinates into Unity‑friendly positions by projecting them onto a plane (e.g., using a simple scale factor for meters per degree) and normalising around the city centre. Simplify geometry by resampling long polylines.
2. **Write a data parser** – Create a C# script (e.g., `TransitParser.cs`) that reads your CSV or JSON and stores stops and segment lists. Use `float.Parse` to convert string fields into floats, and map route IDs to colours/materials. Keep lists of Vector3 positions for each route.
3. **Generate geometry** – In Unity, create prefabs for stations (small spheres or cubes) and for line segments (LineRenderer or thin cylinders). In your script, loop over each route:
- Instantiate a LineRenderer and assign its positions from the route polyline.
- Set the material colour based on the route type (e.g., red line vs green line).
- For each stop, instantiate a station prefab at its position and parent it under the route object.
4. **Anchor in AR** – Parent all transit objects under a single `TransitSystem` GameObject anchored to your detected plane (from AR Foundation or OpenXR). Adjust the scale so that the network fits comfortably on your tabletop. Use colliders and scripts to enable hover highlighting or selection of stations.
5. **Extend interactions & analytics** – Once the network is in Unity, you can tie it into your simulation engine: updating ridership scores as users add new lines, colouring segments based on accessibility, or toggling routes on/off via UI buttons. Combine this with heatmap layers to visualise walking accessibility or demographic impact.
By following these steps, you can integrate transit datasets into your AR/VR projects and build interactive experiences that mirror real city networks.
Contributed by Korey