Save Data in a CSV File Where User Looked Utilizing Pupil Labs Eye Tracking

If you are interested to know if the user has looked at a specific object in the scene in Unity and you want to save that as a csv file, you can follow this tutorial. In this tutorial you will learn how to write a script in Unity using C# prograaming language to save data where the user has looked using Pupil Labs Eye Tracker VR Add on in Unity. If you wish to learn all steps in this documentation in video tutorials, enroll in my course in Udemy Build Complete VR App in Unity with Eye Tracking & EEG.

Requirements

Setup

This tutorial assumes that you have already setup the VR headset and you downloaded SteamVR software and have it running in your computer. If you don't know how to do that you can follow this tutorial. It is also assumed that you have included the pupil labs eye tracker into your VR headset. You can see how that is done here. After all those steps are done, you can continue to the next steps of this tutorial.

Step 1 Create a Unity Project

Open Unity and create your project. Save your scene in Unity however you wish it to be named. If you are not sure how that can be done, follow tutorials from Unity. They have their dedicated page if you are new to Unity Learn Unity here.

Step 2 Create Environment

Start by creating your own environment depending what you are trying to achieve. You can either get for free or purchase a 3D environment already created from Unity Asset Store and import it to Unity. Or you can get an environment from Sketchfab for free or purchase it and import it to Unity. Make sure the format you get the environment is in fbx. Besides Sketchfab there is also CGtrader and Turbosquid. If you wish to create your own environment, you can create a simple one in Unity or you can create one using Blender.

Step 3 Add Box Colliders

In your Unity project you will need now to add box colliders to objects you would like to see if user has looked at it. For example if there is a table in the scene with a 3D model and you would like to see if user is looking at this 3D model, you can add a box collider around this 3D model and add a tag to the box collider. Once you tag the collider you can then check if user has looked at this collider by following the next steps of this tutorial.

Step 4 Download Pupil Core Software

You will now need to download pupil core software here Download Pupil Core Software. Once downloaded open pupil capture from your computer and leave it running. It is important to know that every time you need to use the eye tracker from Unity, pupil capture should be opened and running.

Step 5 Import Eye Tracker Unity Package

To be able to access the pupil labs eye tracker in Unity, you will need to download the latest release of the Unity package for the eye tracker Pupil Labs Eye Tracker Unity Package Under Assets, download Hmd-Eyes unitypackage and import it in Unity. Now you have access to the eye tracker and you can utilize all of its functions in your Unity project.

Step 6 Script

Create a script in Unity using C# programming langugage and name it OnCollisionEye. Copy the code below and paste it to your script in Unity. Add the script into a gameobject in Unity. Depending the tag name that you added in step 3, change the name Intsructions and AllExperiments in codes if(hit.collider.tag == "Instructions") if (hit.collider.tag == "AllExperiments") The script will save the data into your application folder. If you open in your computer the path where you created this Unity project, you can go to Assets and in the Assets folder, create a folder called Data. The data will be saved in Data folder. The function in this script that saves the data is void LookedAtExperiments()
                                            
                                                using System.Collections;
                                                using System.Collections.Generic;
                                                using UnityEngine;
                                                using PupilLabs;
                                                using System;
                                                using UnityEngine.UI;
                                                using System.IO;

                                                public class OnCollisionEye : TimeSync
                                                {
                                                    public GazeVisualizer gazeVisualizer;
                                                    public GazeData gazeData;
                                                    public Transform gazeOriginCamera;
                                                    public GazeController gazeController;

                                                    private void OnEnable()
                                                    {
                                                        if (gazeController)
                                                        {
                                                            gazeController.OnReceive3dGaze += OnReceive;
                                                        }
                                                    }
                                                    private void OnReceive(GazeData obj)
                                                    {
                                                        gazeData = obj;
                                                    }
                                                    // Update is called once per frame
                                                    void Update()
                                                    {
                                                        if(gazeData != null)
                                                        {
                                                            Vector3 origin = gazeOriginCamera.position;
                                                            Vector3 direction = gazeOriginCamera.TransformDirection(gazeData.GazeDirection);

                                                            if(Physics.SphereCast(origin, 0.1f, direction, out RaycastHit hit, Mathf.Infinity))
                                                            {
                                                                if(hit.collider.tag == "Instructions")
                                                                {
                                                                    LookedAtInstructions(); //Calls the function to save the data into csv file
                                                                }
                                                                if (hit.collider.tag == "AllExperiments")
                                                                {
                                                                    LookedAtExperiments(); //Calls another function to save the data into another csv file
                                                                }
                                                            }

                                                            //This script saves data into two csv files but if you are interested to save it to only one file you can make this check:

                                                            /*
                                                            if(hit.collider.tag == "Instructions")
                                                            {
                                                                LookedAt("Instructions"); //We will then need to create a function called LookedAt that takes a string. See below the function LookedAt(); You can remove the comments if you are interested to use that function.
                                                            }
                                                            else if (hit.collider.tag == "AllExperiments")
                                                            {
                                                                LookedAt("Experiments");
                                                            }
                                                            else 
                                                            {
                                                                LookedAt("Else");
                                                            }
                                                            */
                                                        }
                                                    }

                                                    /*
                                                    void LookedAt(string LookedWhere)
                                                    {
                                                        string date = System.DateTime.Now.ToString("yyyy_MM_dd");
                                                        string path = $"{Application.dataPath}/Data/" + "LookedAt.csv";
                                                        double pupilTime = GetPupilTimestamp();
                                                        double unityTime = Time.realtimeSinceStartup;
                                                        if (!File.Exists(path))
                                                        {
                                                            string header = "Pupil Timestamp,Unity Time,Looked At" + Environment.NewLine;
                                                            File.AppendAllText(path, header);
                                                        }
                                                        string values = $"{pupilTime}, {unityTime}, {LookedWhere}" + Environment.NewLine;
                                                        File.AppendAllText(path, values);
                                                    }
                                                    */

                                                    void LookedAtInstructions()
                                                    {
                                                        string date = System.DateTime.Now.ToString("yyyy_MM_dd");

                                                        // Your path to save the data. Application.dataPath means that we will save the data under the Assets folder of your project. 
                                                        //I have also included a folder under the Assets folder and I am saving the data in LookedAtInstructions.csv
                                                        string path = $"{Application.dataPath}/Data/" + "LookedAtInstructions.csv"; 

                                                        double pupilTime = GetPupilTimestamp();
                                                        double unityTime = Time.realtimeSinceStartup;

                                                        if (!File.Exists(path))
                                                        {
                                                            string header = "Pupil Timestamp,Unity Time,Looked At" + Environment.NewLine;

                                                            File.AppendAllText(path, header);
                                                        }

                                                        string values = $"{pupilTime}, {unityTime}, {"Instructions"}" + Environment.NewLine;

                                                        File.AppendAllText(path, values);
                                                    }
                                                    void LookedAtExperiments()
                                                    {
                                                        string date = System.DateTime.Now.ToString("yyyy_MM_dd");

                                                        // Your path to save the data. Application.dataPath means that we will save the data under the Assets folder of your project. 
                                                        //I have also included a folder under the Assets folder and I am saving the data in LookedAtExperimentsModels.csv
                                                        string path = $"{Application.dataPath}/Data/" + "LookedAtExperimentsModels.csv";

                                                        double pupilTime = GetPupilTimestamp();
                                                        double unityTime = Time.realtimeSinceStartup;

                                                        if (!File.Exists(path))
                                                        {
                                                            string header = "Pupil Timestamp,Unity Time,Looked At" + Environment.NewLine;

                                                            File.AppendAllText(path, header);
                                                        }

                                                        string values = $"{pupilTime}, {unityTime}, {"Experiments Models"}" + Environment.NewLine;

                                                        File.AppendAllText(path, values);
                                                    }

                                                }
                                            
                                        

Step 7 Calibrate Eye Tracker

Calibrating the eye tracker is a very important step. Before each data collection it is highly recommended that you calibrate the eye tracker. The calibration process is done to correctly calibrate users eye position. If you wish to learn more on calibration, have a look at their documentation: Pupil Labs User Manual. The user will have to place the VR headset for the calibration process to start. There are two ways in which you can make a calibration:

1- From the Pupil Core Software directly by openning the software and pressing key C on your keyboard.

2- From Unity application itself by including on your scene calibration prefab that comes with the Eye Tracker Unity package and initializing the eye tracker calibration process when needed.

If you wish to follow the second method, you can learn how to do this and all steps mentioned in this documentation by enrolling in my course in Udemy Build Complete VR App in Unity with Eye Tracking & EEG.

Conclusion and More

After you followed all these steps, you can now save the data where user has looked. If you wish to learn all these steps in more details, enroll in my course in Udemy Build Complete VR App in Unity with Eye Tracking & EEG If you would only like to learn how to create the colliders around the 3D models, tag them and use the script, have a look at this video below: