コード例 #1
0
 /**
  * Called by the dataManager object in the RunExperiment script whenever a given trial is completed
  * so that the trial's data can be stored.
  */
 public void AddTrial(ManageTrials.Trial trial)
 {
     // Ensure that we don't try to index past the end of the array
     if (i < data.Length)
     {
         data[i] = new TrialData(trial);
         i++;
     }
 }
コード例 #2
0
        public float ttcEstimate;       // the participant's calculated TTC estimate



        /**
         * The constructor for the TrialData object. It needs to create an array to represent
         */
        public TrialData(ManageTrials.Trial trial)
        {
            this.trialNum   = trial.trialNum;
            TRIALNUM        = SaveData.putTrialNum(trial.trialNum);
            this.trialName  = trial.trialName;
            this.corrAns    = trial.corrAns;
            this.trialStart = trial.trialStart;
            this.trialEnd   = trial.trialEnd;
            this.respTime   = trialEnd - trialStart;
            this.response   = trial.response;
            this.confidence = trial.confidence;



            // Iterate through all objects to create an ObjData object for each object in the trial
            this.objData = new ObjData[trial.objects.Length];
            for (int j = 0; j < trial.objects.Length; j++)
            {
                this.objData[j]  = new ObjData(trial.objects[j]);
                this.ttcEstimate = this.respTime - this.objData[j].timeVisible;
            }
        }
コード例 #3
0
    private GameObject audioSourceObject;      // The object which will play the audio files.


    /**
     * Initializes all trial data once the experiment begins. This includes loading the
     * config file, loading in the trial-information, and setting all experiment-wide variables.
     */
    void Start()
    {
        // Set the target framerate for the application
        Application.targetFrameRate = 90;
        rate = 90.0f;

        // Set the step size for the objects' motion based on the rate
        stepSize = (1.0f / rate);

        // Load the config file
        string configFilepath = Application.dataPath + "/config.json";

        config = GetComponent <ReadConfig>().LoadConfig(configFilepath.Replace("/", "\\"));

        if (config.debugging)
        {
            Debug.Log(configFilepath);
        }

        // Set the feedback display configurations based on the config file
        uiManager.SetFeedbackColor(config.feedbackColor);
        uiManager.SetFeedbackSize(config.feedbackSize);
        if (config.cameraLock)
        {
            uiManager.SetFeedbackPosition(config.feedbackPos[0], config.feedbackPos[1], config.feedbackPos[2], true);
        }
        else
        {
            uiManager.SetFeedbackPosition(config.feedbackPos[0], config.feedbackPos[1], config.feedbackPos[2]);
        }

        // Load the data from the desired input file
        trials = GetComponent <ManageTrials>().LoadTrialData(config.trialFile.Replace("/", "\\"), Time.time);

        // Initialize the TrialData array to be the correct size in the experiment's data manager
        dataManager.InitDataArray(trials.Length, Time.time);

        // Add the config info to the data manager
        dataManager.SetConfigInfo(config);

        // Initialize global variables
        curTrial    = 0;
        isRunning   = false;
        expComplete = false;

        // Set the head position transform to track the participant's movements
        headPos       = GameObject.Find("Camera (eye)").transform;
        controllerPos = GameObject.Find("/CameraManager/[CameraRig]/Controller (right)").transform;
        movingObj     = GameObject.Find("MovingObj");

        // Set the audio source
        audioSourceObject = GameObject.Find("Camera (ears)");

        // Load all audio sources
        for (int i = 0; i < trials.Length; i++)
        {
            ManageTrials.Trial trial = trials[i];

            if (trial.playSound)
            {
                ReadAudioFiles("Assets/Trials/soundFiles/" + trials[i].soundFile);
            }
        }



        // Set up environment.
        if (config.ground)          // Toggle ground visibility.
        {
            ground.SetActive(true); // Make the ground visible.
        }
        else
        {
            ground.SetActive(false); // Toggle off ground visibility.
        }

        if (config.road)                                                                                    // Toggle and set up road.
        {
            road.SetActive(true);                                                                           // Make the ground visible.
            road.transform.position = new Vector3(config.roadPos[0], config.roadPos[1], config.roadPos[2]); // Set position.
        }
        else
        {
            road.SetActive(false); // Toggle off road visibility.
        }
    }
コード例 #4
0
    /**
     * Initialize the current trial.
     */
    public void InitializeTrial()
    {
        // Check that we still have more trials to run
        if (curTrial < this.trials.Length)
        {
            // Stop displaying the feedback text
            uiManager.ResetFeedbackMsg();

            Debug.Log("Trial " + trials[curTrial].trialNum + ": " + trials[curTrial].trialName + " started");

            // Get the current trial from the data array
            ManageTrials.Trial trial = trials[curTrial];


            // Initialize all of the arrays for the objects in the trial
            numObjs              = trial.objects.Length;
            objs                 = new Transform[numObjs];
            startPosArr          = new Vector3[numObjs];
            endPosArr            = new Vector3[numObjs];
            movingObjs           = new Transform[numObjs];
            cusMotArray          = new List <Vector3> [numObjs];
            rotations            = new List <Vector3> [numObjs];
            cusMotArrayIndex     = new int[numObjs];
            numCustomCoordinates = new int[numObjs];

            if (trial.playSound)
            {
                // Play sounds for the trial
                List <AudioClip> trialClips     = audioClips[curTrial];
                List <float>     trialAudioTime = audioDelays[curTrial];

                for (int tcIndex = 0; tcIndex < trialClips.Count; tcIndex++)
                {
                    AudioSource audioSource = audioSourceObject.AddComponent <AudioSource>();
                    Debug.Log("current trial index: " + curTrial);
                    audioSource.clip = trialClips[tcIndex];
                    StartCoroutine(PlaySoundAfterDelay(audioSource, trialAudioTime[tcIndex]));
                }
            }

            for (int i = 0; i < numObjs; i++)
            {
                ManageObjs.Obj curObj = trial.objects[i];

                // Set current frame to 0.
                curFrame = 0;

                // Set custom motion array to empty.
                cusMotArray[i] = new List <Vector3>();

                // Set custom rotations array to empty.
                rotations[i] = new List <Vector3>();

                if (curObj.customMot) // Check for custom motion configurations.
                {
                    // Set custom motion array index to 0.
                    cusMotArrayIndex[i] = 0;
                    // Set custom motion array (called positions) and custom rotations array (called rotations).
                    ReadCustomPositions("Assets/Trials/Custom_Motion_Positions/" + curObj.customFile, i);
                }

                Debug.Log("custom motion array for index " + i + ": ");
                for (int y = 0; y < numCustomCoordinates[i]; y++)
                {
                    Debug.Log(y + ": " + cusMotArray[i][y]);
                }

                // Set the object prefab that will be displayed
                GameObject newObj = Resources.Load("Objects\\" + curObj.objType) as GameObject;
                objs[i] = newObj.transform;

                // Set the scale of the object
                objs[i].localScale = new Vector3(curObj.objScale[0], curObj.objScale[1], curObj.objScale[2]);

                // Set the object rotation.
                if (curObj.customMot && (objs[i].localEulerAngles != rotations[i][0]))
                {
                    Debug.Log("WARNING! Object rotation is not equal to initial rotation in custom motion file. Using the rotation of first frame in " + curObj.customFile);
                    objs[i].localEulerAngles = rotations[i][0];
                }

                if (!curObj.customMot)
                {
                    objs[i].localEulerAngles = new Vector3(curObj.objRot[0], curObj.objRot[1], curObj.objRot[2]);
                }

                if (config.debugging)
                {
                    Debug.Log("rotation: " + objs[i].localEulerAngles.x + " " + objs[i].localEulerAngles.y + " " + objs[i].localEulerAngles.z);
                }

                /**
                 * Check that offsets are merely directions and don't have a magnitude. If so, correct them.
                 */

                if (Math.Abs(curObj.offsetX) > 1)
                {
                    Debug.Log("WARNING! Magnitude of x offset direction should not be greater than 1!");
                    curObj.offsetX = curObj.offsetX / Math.Abs(curObj.offsetX);
                }
                if (Math.Abs(curObj.offsetY) > 1)
                {
                    Debug.Log("WARNING! Magnitude of y offset direction should not be greater than 1!");
                    curObj.offsetY = curObj.offsetY / Math.Abs(curObj.offsetY);
                }
                if (Math.Abs(curObj.offsetZ) > 1)
                {
                    Debug.Log("WARNING! Magnitude of z offset direction should not be greater than 1!");
                    curObj.offsetZ = curObj.offsetZ / Math.Abs(curObj.offsetZ);
                }

                // Set offset directions.
                Vector3 offsetDirections = new Vector3(curObj.offsetX, curObj.offsetY, curObj.offsetZ);

                // Set initial start and end vectors.
                Vector3 startVector = new Vector3(curObj.startPos[0], curObj.startPos[1], curObj.startPos[2]);
                Vector3 endVector   = new Vector3(curObj.endPos[0], curObj.endPos[1], curObj.endPos[2]);

                if (curObj.customMot && (startVector != cusMotArray[i][0] || endVector != cusMotArray[i][numCustomCoordinates[i] - 1]))
                {
                    Debug.Log("WARNING! Custom motion initial and final positions in " + curObj.customFile +
                              " are not equal to startPos and endPos. Using initial and final positions in " + curObj.customFile);
                }

                // Get size of model
                Renderer render  = objs[i].GetComponent <Renderer>();
                Vector3  objSize = render.bounds.size;

                if (config.cameraLock)
                {
                    startPosArr[i] = new Vector3(startVector.x, startVector.y, startVector.z); // Got rid of adding camera height because was doing it twice.
                    endPosArr[i]   = new Vector3(endVector.x, endVector.y, endVector.z);

                    // Calculate camera lock offsets
                    if (curObj.customMot)
                    {
                        CameraLockOffset(cusMotArray[i], objSize, offsetDirections);
                    }

                    else
                    {
                        List <Vector3> startEndList = new List <Vector3>();
                        startEndList.Add(startPosArr[i]);
                        startEndList.Add(endPosArr[i]);
                        List <Vector3> positions = CameraLockOffset(startEndList, objSize, offsetDirections);
                        startPosArr[i] = positions[0];
                        endPosArr[i]   = positions[1];
                    }
                }
                else
                { // Add offsets for non camera-locked trials.
                    // Initialize startPosArr and endPosArr with a copy of the object's current start and end positions, respectively.
                    startPosArr[i] = startVector;
                    endPosArr[i]   = endVector;

                    // Calculate offsets
                    if (curObj.customMot)
                    {
                        Offset(cusMotArray[i], objSize, offsetDirections);
                    }

                    else
                    {
                        List <Vector3> startEndList = new List <Vector3>();
                        startEndList.Add(startPosArr[i]);
                        startEndList.Add(endPosArr[i]);
                        List <Vector3> positions = Offset(startEndList, objSize, offsetDirections);
                        startPosArr[i] = positions[0];
                        endPosArr[i]   = positions[1];
                    }
                }


                // Calculate the distance that the object must travel
                curObj.dist = Vector3.Distance((Vector3)startPosArr[i], (Vector3)endPosArr[i]);

                if (config.debugging)
                {
                    Debug.Log("Start Pos: " + startPosArr[i].x + " " + startPosArr[i].y + " " + startPosArr[i].z);
                }
                if (config.debugging)
                {
                    Debug.Log("End Pos: " + endPosArr[i].x + " " + endPosArr[i].y + " " + endPosArr[i].z);
                }

                // Instantiate the object so that it's visible
                if (curObj.customMot)
                {
                    movingObjs[i] = Instantiate(objs[i], cusMotArray[i][0], objs[i].localRotation); // Important to make sure these are correct variables.
                }

                else
                {
                    movingObjs[i] = Instantiate(objs[i], startPosArr[i], objs[i].localRotation); // Important to make sure these are correct variables.
                }
                curObj.objVisible = true;
                curObj.objActive  = true;
                if (config.feedbackType == 1)
                {
                    pmVisible = true;
                }

                // Set the variables that need to be used in the repeating method to move the objects
                curObj.step      = curObj.velocity * stepSize;
                curObj.finalStep = ((curObj.dist / curObj.velocity) * rate);

                //calculate theoretical ttcActual
                ttcActual = ((curObj.startPos[2] - (curObj.timeVisible * curObj.velocity)) / curObj.velocity);
                if (config.debugging)
                {
                    Debug.Log("TTC: " + ttcActual);
                }

                // If timeVisible is negative, the object should never disappear
                if (curObj.timeVisible < 0)
                {
                    curObj.stepHidden = -1;     // set stepHidden to be a step value that can never occur so that HideObject will never be called
                }
                else
                {
                    curObj.stepHidden = curObj.timeVisible * rate;
                }
            }
            // Set the start time of this trial so that it can be recorded by the data manager
            trial.trialStart = Time.time;
            curTrial++;
            // Call the repeating methods to move the objects and track head position
            float delay = (1.0f / rate);
            InvokeRepeating("MoveObjsByStep", 0.0f, delay);
            InvokeRepeating("Tracking", 0.0f, delay);

            // Set the trial as running
            isRunning = true;
        }
        else
        {
            // Do this check and then increment the trial num so data is only saved once
            if (curTrial == trials.Length)
            {
                expComplete = true;
                if (config.debugging)
                {
                    Debug.Log("Experiment complete");
                }
                uiManager.ShowMessage("Experiment complete");
                dataManager.Save(false);
                curTrial++;
            }
        }
    }