Skip to content

Multi scene experiments

Jack Brookes edited this page Jun 4, 2021 · 12 revisions

More complex experiments will use more than one scene, switching to different environments. It can be tricky to maintain the experiment logic in these cases. There is an example experiment as of the August 2020 release of UXF which demonstrates how you might do this. There are several features that make creating multi-scene experiments easier:

Singleton access

As of the August 2020 release, you can optionally access the UXF Session as a "singleton", a common but controversial program architecture. It is enabled by default, with a new "Set As Main Instance" option in the UXF Session component. This will make that session be accessible anywhere with UXF.Session.instance, meaning you do not need a reference to the UXF Session when you need to start the trial, add results, change settings, etc. When used in combination with another option "Don't Destroy On Load New Scene", this means that when you load into a new scene, perhaps for a special type of trial, the UXF Session will not be destroyed, and your scripts will be able to find it. Example script:

Access UXF session with public reference (old behaviour):

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

// add the UXF namespace
using UXF;

public class MyExample: MonoBehaviour
{     

    public Session session; // reference to session, needs to be assign in the inspector

    public void DoSomething()
    {
        // some example you might use with the session component
        session.CurrentTrial.Begin();
        ShowInstructions(session.CurrentTrial.settings.GetString("instructions")); 
        session.CurrentTrial.result["response"] = 12345;
    }

    ...

}

Same, but accessing with the new "Singleton" method:

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

// add the UXF namespace
using UXF;

public class MyExample: MonoBehaviour
{     

    // direct reference to session not needed

    public void DoSomething()
    {
        // some example you might use with the session component
        Session.instance.CurrentTrial.Begin();
        ShowInstructions(Session.instance.CurrentTrial.settings.GetString("instructions")); 
        Session.instance.CurrentTrial.result["response"] = 12345;
    }

    ...

}

Handling tracked object in multiple scenes

If you want to track different objects (using the Tracking system) that are different across scenes, there are a few options.

  1. One way to solve this is make a GameObject called e.g. "Tracker" with the PositionRotationTracker component attached, then you can just reparent this Tracker GameObject to any object in the scene as you need. You can make this object DontDestroyOnLoad (see Unity docs) and get a reference to the Gameobject you need (carefully) with e.g. GameObject.Find.
if (trialType == "hand")
{    
    tracker.transform.parent = GameObject.Find("Hand").transform;
    tracker.transform.localPosition = Vector3.zero;
    tracker.transform.localRotation = Quaternion.identity;
}
else if (trialType == "tool")
{    
    tracker.transform.parent = GameObject.Find("Tool").transform;
    tracker.transform.localPosition = Vector3.zero;
    tracker.transform.localRotation = Quaternion.identity;
}
  1. Another way would be to use the new "Ad Hoc Header Add" setting in the Session component. You can edit the session.trackedObjects via script, and then remove that object from the list after the trial has ended. The "Ad Hoc Header Add" setting means the same trackers do not need to be referenced on each trial. Below is an option for adding a PositionRotationTracker referenced as foot:
// starting your trial
session.NextTrial.Begin();
session.trackedObjects.Add(foot);

... // your trial happens

// ending your trial
session.CurrentTrial.End();
session.trackedObjects.Remove(foot); // <-- IMPORTANT, REMOVE AFTER TRIAL ENDED, NOT BEFORE

๐Ÿง  Core topics

โ“ More help


๐Ÿ‘ฉโ€๐Ÿ’ป Programming reference

Unit tests

Clone this wiki locally