med-material / Whack_A_Mole_VR

Whack-A-Mole in VR
MIT License
3 stars 15 forks source link

Update the Architecture of the Out of Bound Indicators of MotorSpace #254

Open tcaruchet opened 1 year ago

tcaruchet commented 1 year ago

This issue aims to improve the architecture and flexibility of the out of bound indicators, implementing both static and dynamic variants, and providing the ability to easily switch between them, through the Therapist UI. The following are the detailed requirements for this update:

  1. OutOfBoundIndicator Interface: Create an abstract class OutOfBoundIndicator to enforce the structure and methods necessary for an out of bound indicator. The abstract should define the following methods:

    • ShowIndicator(Vector3 outOfBoundPosition, Vector3 motorSpacePosition, Side nearestSide)
    • HideIndicator()
  2. Static Arrow Indicator: Create a class StaticArrowIndicator that implements OutOfBoundIndicator. When shown, it should simply display multiple arrows pointing towards the MotorSpace, around the bubble controller. It does not need to update its orientation in real-time (Old Implementation).

  3. Dynamic Center Pointing Indicator: Create a class DynamicCenterPointingIndicator that also implements OutOfBoundIndicator. When shown, it should continuously point towards the center of the MotorSpace, updating its orientation in real-time as the user moves with the animation already inside the codebase.

  4. Indicator Manager: Add a private variable outOfBoundIndicatorManager to the BubbleDisplay class. This will hold the current active OutOfBoundIndicator. Depending on the current requirements, this can be either an instance of StaticArrowIndicator or DynamicCenterPointingIndicator.

  5. Switching Indicators: Implement a method ChangeIndicator(ArrowType arrowType) in BubbleDisplay to switch the current active OutOfBoundIndicator. The ArrowType (enum) can be StaticPointing or PointingCenter.

  6. Time Tracking: Implement a timer to track the time between when the user exits the MotorSpace and when they re-enter. This should be logged when the user re-enters the MotorSpace, with the type of indicator that was active. To analyze it.

bastianilso commented 1 year ago

@tcaruchet sounds like a good plan and helpful technical architecture for the experiment!

tcaruchet commented 1 year ago

Update on MotorSpace Out-of-Bound Indicators

On my fork : https://github.com/tcaruchet/Whack_A_Mole_VR

I've implemented two types of indicators for exiting the MotorSpace: static and dynamic.

Static indicator is the old version of the system present in the codebase where the MotorSpace is displayed along with animated arrows pointing to the center all around it. Screenshot 2023-07-05 152222

Dynamic indicator is the current arrow system.

The architecture has been updated with the new abstraction. An OutOfBoundsManager has been created in the MainScene with the 4 GameObjects for Static and Dynamic indicators for the right and left hands. All indicators are colored the same as the pointer.

A test pattern (.wampat) is being developed to conduct the study. However, it needs to be determined whether the mole appearances are randomized or whether the same game experience is provided to all participants of the upcoming study.

The time spent outside of each MotorSpace is saved in the CSV Event for analysis purposes. This is to measure the ability to return inside the MotorSpace and evaluate the effectiveness of a given indicator system.

tcaruchet commented 1 year ago

I have troubles to save MotorSpace exiting event correctly in the CSV file.

Events.xlsx

The colums aren't correctly set. Maybe my code isn't well good to logging (from BubbleDisplay.cs)... :

// Log the time spent outside the MotorSpace and the type of indicator used
    private void LogReturnTime()
    {
        // Check if the user has already exited the MotorSpace
        if (hasExited)
        {
            TimeSpan timeSpentOutside = DateTime.Now - exitTime;
            // Log the time spent outside
            Debug.Log($"Time spent outside the MotorSpace: {timeSpentOutside.TotalSeconds} seconds. Indicator type: {outOfBoundIndicatorManager.GetType().Name}");
            // Reset the exit time and the hasExited flag
            hasExited = false;

            GameObject[] controllers = laserMapper.GetActiveControllers();
            GameObject controller = controllers.LastOrDefault(c => c.activeSelf);
            loggingManager.Log("Event", new Dictionary<string, object>()
            {
                {"Event", "MotorSpace Exiting Time"},
                {"EventType", "MotorSpaceEvent"},
                { "TimeSpentOutsideMotorSpace", timeSpentOutside },
                { "TimeSpentOutsideMotorSpaceSeconds", timeSpentOutside.TotalSeconds },
                { "IndicatorType", CurrentArrowType.ToString() },
                { "Side", LastLaserMapperNearestSide },
                {"ControllerName", controller.name},
                {"ControllerOffset", controller.GetComponent<SteamVR_Behaviour_Pose>().inputSource},
                { "Timestamp", DateTime.Now }

            });
        }

    }