private void KeepOnLoad()
    {
        // Keep player and avatar objects
        GameObject playerGO = GameObject.FindGameObjectWithTag("Player");
        GameObject avatarGO = GameObject.FindGameObjectWithTag("Avatar");

        if (playerGO == null || avatarGO == null)
        {
            MonitorManager.DisplayText("The user or avatar has not been loaded.");
            throw new System.Exception("The player or avatar has not been loaded.");
        }
        DontDestroyOnLoad(playerGO);
        DontDestroyOnLoad(avatarGO);
    }
    // Update is called once per frame
    protected override void Update()
    {
        switch (experimentState)
        {
        /*
         *************************************************
         *  HelloWorld
         *************************************************
         */
        // Welcome subject to the virtual world.
        case ExperimentState.Welcome:
            if (debug)
            {
                LoadDebugAvatar();
                InitialiseExperimentSystems();
                InitializeUI();
            }

            MonitorManager.DisplayText("Instructions:\n" + instructionsText);
            experimentState = ExperimentState.Initialising;
            break;

        /*
         *************************************************
         *  InitializingApplication
         *************************************************
         */
        // Perform initialization functions before starting experiment.
        case ExperimentState.Initialising:
            //
            // Perform experiment initialization procedures
            //

            //
            // Initialize data logs
            //

            //
            // Go to training
            //
            experimentState = ExperimentState.Training;
            break;

        /*
         *************************************************
         *  Practice
         *************************************************
         */
        // Perform initialization functions before starting experiment.
        case ExperimentState.Training:
            //
            // Guide subject through training
            //

            //
            // Go to instructions
            //
            experimentState = ExperimentState.Instructions;
            break;

        /*
         *************************************************
         *  GivingInstructions
         *************************************************
         */
        case ExperimentState.Instructions:
            //
            // Go to waiting for start
            //
            HudManager.DisplayText("Loading...", 2.0f);
            // Turn targets clear
            experimentState = ExperimentState.WaitingForStart;

            break;

        /*
         *************************************************
         *  WaitingForStart
         *************************************************
         */
        case ExperimentState.WaitingForStart:

            // Check if pause requested
            UpdatePause();
            switch (waitState)
            {
            // Waiting for subject to get to start position.
            case WaitState.Waiting:
                SetWaitFlag(3.0f);
                waitState = WaitState.Countdown;
                break;

            case WaitState.Countdown:
                if (WaitFlag)
                {
                    // Enable training camera
                    TrainingCamera.enabled = true;
                    experimentState        = ExperimentState.PerformingTask;
                }
                break;

            default:
                break;
            }
            break;

        /*
         *************************************************
         *  PerformingTask
         *************************************************
         */
        case ExperimentState.PerformingTask:
            // Task performance is handled deterministically in FixedUpdate.
            break;

        /*
         *************************************************
         *  AnalizingResults
         *************************************************
         */
        case ExperimentState.AnalizingResults:
            // Allow 3 seconds after task end to do calculations
            SetWaitFlag(3.0f);

            //
            // Data analysis and calculations
            //

            //
            // System update
            //

            //
            // Data logging
            //

            //
            // Flow managment
            //
            // Rest for some time when required
            if (IsRestTime())
            {
                SetWaitFlag(RestTime);
                experimentState = ExperimentState.Resting;
            }
            // Check whether the new session condition is met
            else if (IsEndOfSession())
            {
                experimentState = ExperimentState.InitializingNext;
            }
            // Check whether the experiment end condition is met
            else if (IsEndOfExperiment())
            {
                experimentState = ExperimentState.End;
            }
            else
            {
                experimentState = ExperimentState.UpdatingApplication;
            }
            break;

        /*
         *************************************************
         *  UpdatingApplication
         *************************************************
         */
        case ExperimentState.UpdatingApplication:
            if (WaitFlag)
            {
                //
                // Update iterations and flow control
                //

                //
                // Update log requirements
                //

                //
                //
                // Go to start of next iteration
                experimentState = ExperimentState.WaitingForStart;
            }
            break;

        /*
         *************************************************
         *  InitializingNext
         *************************************************
         */
        case ExperimentState.InitializingNext:
            //
            // Perform session closure procedures
            //

            //
            // Initialize new session variables and flow control
            //
            iterationNumber = 1;
            sessionNumber++;
            skipInstructions = true;

            //
            // Initialize data logging
            //
            //ExperimentSystem.GetActiveLogger(1).AddNewLogFile(sessionNumber, iterationNumber, "Data format");

            experimentState = ExperimentState.Initialising;     // Initialize next session
            break;

        /*
         *************************************************
         *  Resting
         *************************************************
         */
        case ExperimentState.Resting:
            //
            // Check for session change or end request from experimenter
            //
            if (UpdateNext())
            {
                ConfigureNextSession();
                break;
            }
            else if (UpdateEnd())
            {
                EndExperiment();
                break;
            }
            //
            // Restart after flag is set by wait coroutine
            //
            if (WaitFlag)
            {
                HudManager.DisplayText("Get ready to restart!", 3.0f);
                SetWaitFlag(5.0f);
                experimentState = ExperimentState.UpdatingApplication;
                break;
            }
            break;

        /*
         *************************************************
         *  Paused
         *************************************************
         */
        case ExperimentState.Paused:
            //
            // Check for session change or end request from experimenter
            //
            UpdatePause();
            if (UpdateNext())
            {
                ConfigureNextSession();
                break;
            }
            else if (UpdateEnd())
            {
                EndExperiment();
                break;
            }
            break;

        /*
         *************************************************
         *  End
         *************************************************
         */
        case ExperimentState.End:
            //
            // Update log data and close logs.
            //
            EndExperiment();
            break;

        //
        // Return to main menu
        //
        default:
            break;
        }

        //
        // Update information displayed on monitor
        //

        //
        // Update information displayed for debugging purposes
        //

        //
        // Update HUD state
        //
        if (elbowManager.IsEnabled)
        {
            trainingHudManager.colour = HUDManager.HUDColour.Blue;
        }
        else
        {
            trainingHudManager.colour = HUDManager.HUDColour.Red;
        }
    }
    /// <summary>
    /// Initializes the ExperimentSystem and its components.
    /// Verifies that all components needed for the experiment are available.
    /// </summary>
    public override void InitialiseExperimentSystems()
    {
        //
        // Set the experiment type and ID
        //
        if (AvatarSystem.AvatarType == AvatarType.AbleBodied)
        {
            experimentType = ExperimentType.TypeOne;
            MonitorManager.DisplayText("Wrong avatar used. Please use a Transhumeral avatar.");
            throw new System.Exception("Able-bodied avatar not suitable for prosthesis training.");
        }
        else if (AvatarSystem.AvatarType == AvatarType.Transhumeral)
        {
            // Check if EMG is available
            bool EMGAvailable = false;
            foreach (ISensor sensor in AvatarSystem.GetActiveSensors())
            {
                if (sensor.GetSensorType().Equals(SensorType.EMGWiFi))
                {
                    EMGAvailable = true;
                    UDPSensorManager udpSensor = (UDPSensorManager)sensor;
                    udpSensor.StartSensorReading();
                }
                else if (sensor.GetSensorType().Equals(SensorType.ThalmicMyo))
                {
                    EMGAvailable = true;
                }
            }
            // Set whether emg or synergy based
            if (EMGAvailable)
            {
                experimentType   = ExperimentType.TypeTwo;
                instructionsText = emgInstructions;
                // Set EMG sensor and reference generator as active.
                // Get prosthesis
                GameObject prosthesisManagerGO = GameObject.FindGameObjectWithTag("ProsthesisManager");
                elbowManager = prosthesisManagerGO.GetComponent <ConfigurableElbowManager>();
                // Set active sensor and reference generator to EMG.
                //elbowManager.ChangeSensor("VAL_SENSOR_SEMG");
                elbowManager.ChangeSensor("VAL_SENSOR_THALMYO");
                elbowManager.ChangeReferenceGenerator("VAL_REFGEN_EMGPROP");
            }
            else
            {
                experimentType   = ExperimentType.TypeThree;
                instructionsText = synergyInstructions;
                // Set VIVE tracker and Jacobian synergy as active.
                // Get prosthesis
                GameObject prosthesisManagerGO = GameObject.FindGameObjectWithTag("ProsthesisManager");
                elbowManager = prosthesisManagerGO.GetComponent <ConfigurableElbowManager>();
                if (elbowManager.GetInterfaceType() == ReferenceGeneratorType.JacobianSynergy)
                {
                    // Set the reference generator to jacobian-based.
                    elbowManager.ChangeSensor("VAL_SENSOR_VIVETRACKER");
                    elbowManager.ChangeReferenceGenerator("VAL_REFGEN_JACOBIANSYN");
                }
                else if (elbowManager.GetInterfaceType() == ReferenceGeneratorType.LinearKinematicSynergy)
                {
                    // Set the reference generator to linear synergy.
                    elbowManager.ChangeSensor("VAL_SENSOR_VIVETRACKER");
                    elbowManager.ChangeReferenceGenerator("VAL_REFGEN_LINKINSYN");
                }
                else
                {
                    throw new System.Exception("The prosthesis interface available is not supported.");
                }
            }

            if (!debug)
            {
                // Find the residual limb and change the follower
                residualLimbGO               = GameObject.FindGameObjectWithTag("ResidualLimbAvatar");
                limbFollower                 = residualLimbGO.GetComponent <LimbFollower>();
                limbFollower.enabled         = false;
                angleFollower                = residualLimbGO.AddComponent <AngleFollower>();
                angleFollower.fixedTransform = fixedProsthesisPosition;
            }
        }
        else
        {
            throw new System.NotImplementedException();
        }

        // Get Raycast Debug info
        // handGO = GameObject.FindGameObjectWithTag("Hand");
        // elbowGO = GameObject.FindGameObjectWithTag("Elbow_Upper");
        // residualLimbGO = GameObject.FindGameObjectWithTag("ResidualLimbAvatar");
    }