/// <summary> /// Creates the file to be saved and saves to disk /// </summary> private void CreateFile() { ExperimentLog.Log("Creating file"); var sb = new StringBuilder(); //Append Exp result headers sb.AppendLine("Event_Time" + "," + "Timer_Time" + "," + "Participant_Id" + "," + "Ball_Number" + "," + "Ball_Type" + "," + "Ball_Speed" + "," + "Ball_Result [Miss->0|1 : MaybeHit->2 : HitPastHalf->3 : Goal->4]" + "," + "Game_Points" + "," + "Level"); //Append Exp results foreach (var data in expResults) { sb.AppendLine(data.ToString()); } //Append Log Headers sb.AppendLine("\n\n"); sb.AppendLine("Event_Time" + "," + "Tag" + "," + "Message"); //Append Log Results foreach (var data in LogFileList) { sb.AppendLine(data.ToString()); } string modeStr = TactileAndAudio ? "_tac_aud_" : "_aud_"; var path = EditorUtility.SaveFilePanel( "Save Experiment as CSV", "", nameField.text + modeStr + "_exp.csv", "csv"); if (path.Length != 0) { File.WriteAllBytes(path, new UTF8Encoding().GetBytes(sb.ToString())); } }
/// <summary> /// Click listener that starts the game. Must have player press a button and the researcher press start /// </summary> private void StartExp() { ExperimentLog.Log("Attempted to Start Experiment"); if (canPressStartButton && playerReady) { canPressStartButton = false; clockTimer.Start(); startTime = DateTime.Now; StartNextBall(HitRes.hitNotPastHalf); //Starting game, params don't matter here. ResetGamePoints(); } }
/// <summary> /// Pulls up a GUI menu and based on selected option saves a CSV file with the data and log file. /// </summary> private void SaveCSV() { newBallOk = false; //NumberSpeech.PlayAudio("thanks"); //yield return new WaitForSeconds(2); AudioListener.pause = true; int option = EditorUtility.DisplayDialogComplex("Finish Experiment", "Are you sure you want to finish this experiment?", "Save", "Cancel", "Quit Without Saving"); switch (option) { // Save case 0: Destroy(_currentBall); CreateFile(); menuGameObject.SetActive(true); newBallOk = false; clockTimer.Stop(); ResetExp(); MenuScript.SetMainSelectableAndAudio(); break; // Cancel. case 1: newBallOk = true; break; // Quit Without saving. case 2: Destroy(_currentBall); menuGameObject.SetActive(true); clockTimer.Stop(); newBallOk = false; ResetExp(); MenuScript.SetMainSelectableAndAudio(); break; default: Debug.LogError("Unrecognized option."); ExperimentLog.Log("Error in save menu", tag: "Error"); break; } AudioListener.pause = false; canPressButton = true; }
public void DebugPrint(String s, DebugType d) { if (debug_type == DebugType.NONE) { return; } if (d == DebugType.ALL || d == debug_type || debug_type == DebugType.ALL) { if (s.Contains("connected")) { Debug.LogWarning(s); ExperimentLog.Log("Joycon Connected"); } else { Debug.Log(s); ExperimentLog.Log(s, "Joycon"); } } }
private void Start() { if (JoyconManager.Instance == null) { SceneManager.LoadSceneAsync("GlobalInit", LoadSceneMode.Single); return; } GameUtils.playState = GameUtils.GamePlayState.ExpMode; GameUtils.ballSpeedPointsEnabled = false; _currBallNumber = -1; CreateBallPosition(); ShuffleArray(); saveExpButton.onClick.AddListener(FinishExp); startExpButton.onClick.AddListener(StartExp); numberSpeech = globalSpeechGameObject.GetComponent <NumberSpeech>(); _audioSources = GetComponents <AudioSource>(); levelUpAudio = _audioSources[14]; BallScript.GameInit = false; playerReady = false; batSound = batObj.GetComponents <AudioSource>()[0]; batSound.mute = true; StartCoroutine(GameUtils.PlayIntroMusic()); newBallOk = true; canPressButton = true; clockTimer = new Timer(100); clockTimer.Elapsed += ClockTimer_Elapsed; globalTimer = new Timer(100); globalTimer.Elapsed += GlobalTimer_Elapsed; globalTimer.Start(); ExperimentLog.Log("Program Started", time: DateTime.Now.ToLongTimeString()); gamePoints = 0; canPressStartButton = true; expState = ExpState.menus; playerLevel = 0; past6Min = false; prevHits = new int[6] { 0, 0, 0, 0, 0, 0 }; SetupChildAudio(); }
/// <summary> /// Checks if a player can level by checking if the last 6 hits were hit or not. /// </summary> /// <returns></returns> private bool CheckLevelUp() { int hits = 0; foreach (int h in prevHits) { if (h == 1) { hits++; } } if (hits > 3) // 4 out of 6 hits, level up! { prevHits = new int[6] { 0, 0, 0, 0, 0, 0 }; ExperimentLog.Log("Level Up: " + (playerLevel + 1), tag: "Exp"); return(true); } return(false); }
/// <summary> /// Audio for next ball and calls spawnBall to start a new ball /// </summary> /// <returns></returns> private IEnumerator NextBallComing() { if ((UnityEngine.Random.Range(0, 3) == 0 && _currBallNumber != -1 && gamePoints != 1) || _currBallNumber == 29) //Randomly 1/3 of the time say how many points { ExperimentLog.Log("Read the Score"); StartCoroutine(numberSpeech.PlayExpPointsAudio(gamePoints)); yield return(new WaitForSeconds(4.5f)); //Wait 4.5 seconds for points audio to finish } else if (!IsAnnounceBall) { AudioSource aud = NumberSpeech.PlayAudio("nextball"); yield return(new WaitForSeconds(aud.clip.length + 0.2f)); } yield return(SpawnBall()); timerStarted = true; oldTime = Time.time; newBallOk = true; }
/// <summary> /// Starts the next ball and adds to the total gamePoints /// </summary> /// <param name="hitres"></param> /// <param name="pointsToAdd"></param> private void StartNextBall(HitRes hitres) { if (playerReady && !canPressStartButton) { if (newBallOk) { newBallOk = false; Debug.Log("Sending Ball"); ExperimentLog.Log("Sending Ball"); if (_currBallNumber != -1) { if (GoalScript.ExpBallWin) { GoalScript.ExpBallWin = false; hitres = HitRes.goal; } gamePoints += hitres == HitRes.miss ? 0 : (int)hitres - 1;//The points correlate to the hitres CollectExpData(hitres); } Destroy(_currentBall); if (_currBallNumber != -1) { StartCoroutine((hitres != HitRes.miss && hitres != HitRes.tipped) ? NextBallHit() : NextBallMissed(hitres)); } else { StartCoroutine(NextBallComing()); } } } else { Debug.LogWarning("Exp Not Started"); ExperimentLog.Log("Exp Not Started", tag: "warn"); } }
private void SetupButtonClickListeners() { AudioOnlyButton.onClick.AddListener(() => { ExperimentLog.Log("Pressed Exp Mode", "Menu"); ExpManager.TactileAndAudio = false; menuGameObject.SetActive(false); mainMenuGO.SetActive(true); expMenuText.text = "Audio Only Exp"; Time.timeScale = 1; if (!SceneManager.GetActiveScene().name.Equals("Master")) { SceneManager.LoadSceneAsync("Master", LoadSceneMode.Single); } currAudioList = expAudioList; currSelectableList = expSelectableList; ToggleTopButton(); }); tactileAndAudioButton.onClick.AddListener(() => { ExperimentLog.Log("Pressed Naive Mode", "Menu"); ExpManager.TactileAndAudio = true; menuGameObject.SetActive(false); mainMenuGO.SetActive(true); Time.timeScale = 1; expMenuText.text = "Tactile & Audio Exp"; if (!SceneManager.GetActiveScene().name.Equals("Master")) { SceneManager.LoadSceneAsync("Master", LoadSceneMode.Single); } currAudioList = expAudioList; currSelectableList = expSelectableList; ToggleTopButton(); }); freeButton.onClick.AddListener(() => { Time.timeScale = 1; ExperimentLog.Log("Pressed Free play Mode", "Menu"); SceneManager.LoadSceneAsync("SinglePlayer", LoadSceneMode.Single); }); startRightHand.onClick.AddListener(() => { if (!partInputField.text.Equals("")) { ExperimentLog.Log("Clicked [Start Right Hand]", tag: "pre-menu"); StartCalbMenu(false); } else { ExperimentLog.Log("Missing Participant ID", tag: "pre-menu"); Debug.LogWarning("Missing Participant ID"); GetComponents <AudioSource>()[1].Play(); } currSelectableList = calibSelectableList; currAudioList = calibAudioSourceList; ToggleTopButton(); }); startLeftHand.onClick.AddListener(() => { if (!partInputField.text.Equals("")) { ExperimentLog.Log("Clicked [Start Right Hand]", tag: "pre-menu"); StartCalbMenu(true); } else { ExperimentLog.Log("Missing Participant ID", tag: "pre-menu"); Debug.LogWarning("Missing Participant ID"); GetComponents <AudioSource>()[1].Play(); } currSelectableList = calibSelectableList; currAudioList = calibAudioSourceList; ToggleTopButton(); }); calibrateButton.onClick.AddListener(() => { //If a JoyCon Button is pressed for the first time, then //the calibration in Exp Manager will be set. JoyconController.ButtonPressed = true; calibrationGO.SetActive(false); mainMenuGO.SetActive(true); currSelectableList = mainSelectableList; currAudioList = mainAudioSouceList; ToggleTopButton(); }); }
/// <summary> /// Plays audio for a correction hint based on a hit result of the last ball /// This is a Coroutine menthod and by nature is async /// </summary> /// <param name="hitRes">The results of the last ball</param> /// <returns></returns> private IEnumerator ReadHitCorrection(HitRes hitRes) { var snapShotBatPos = endSnapshot.batPos; var snapShotBallPos = endSnapshot.ballPos; float absDist = Math.Abs(snapShotBatPos.x - snapShotBallPos.x); if (hitRes == HitRes.tipped) { if (CollisionSnapshot.ballPos.x < CollisionSnapshot.batPos.x - 5) { tippedAudio.Play(); yield return(new WaitForSeconds(tippedAudio.clip.length)); ExperimentLog.Log("Tipped to the left"); reachLeft.Play(); yield return(new WaitForSeconds(reachLeft.clip.length)); } else if (CollisionSnapshot.ballPos.x > CollisionSnapshot.batPos.x + 5) { tippedAudio.Play(); yield return(new WaitForSeconds(tippedAudio.clip.length)); reachRight.Play(); yield return(new WaitForSeconds(reachRight.clip.length)); ExperimentLog.Log("Tipped to the right"); } else if (CollisionSnapshot.ballPos.z < CollisionSnapshot.batPos.z) { ExperimentLog.Log("You hit the ball backward"); backwardAudio.Play(); yield return(new WaitForSeconds(backwardAudio.clip.length)); } } else if (absDist < 10) { if (snapShotBatPos.z > snapShotBallPos.z) { //Reached too far forward too soon. tooForward.Play(); yield return(new WaitForSeconds(tooForward.clip.length)); } else { //Reached too far back tooBack.Play(); yield return(new WaitForSeconds(tooBack.clip.length)); } } else if (snapShotBallPos.x > 0 && snapShotBallPos.x > snapShotBatPos.x) { //Reach further to the right float distOff = snapShotBallPos.x - snapShotBatPos.x; reachRight.Play(); yield return(new WaitForSeconds(reachRight.clip.length)); StartCoroutine(numberSpeech.PlayFancyNumberAudio((int)distOff)); yield return(new WaitForSeconds(2.5f)); } else if (snapShotBallPos.x > 0 && snapShotBallPos.x < snapShotBatPos.x) { //Too far to the right float distOff = snapShotBatPos.x - snapShotBallPos.x; tooRight.Play(); yield return(new WaitForSeconds(tooRight.clip.length)); StartCoroutine(numberSpeech.PlayFancyNumberAudio((int)distOff)); yield return(new WaitForSeconds(2.5f)); } else if (snapShotBallPos.x < 0 && snapShotBallPos.x > snapShotBatPos.x) { //Too far to the left float distOff = Math.Abs(snapShotBatPos.x - snapShotBallPos.x); tooLeft.Play(); yield return(new WaitForSeconds(tooLeft.clip.length)); StartCoroutine(numberSpeech.PlayFancyNumberAudio((int)distOff)); yield return(new WaitForSeconds(2.5f)); } else if (snapShotBallPos.x < 0 && snapShotBallPos.x < snapShotBatPos.x) { //Reach futher to the left float distOff = Math.Abs(snapShotBallPos.x - snapShotBatPos.x); reachLeft.Play(); yield return(new WaitForSeconds(reachLeft.clip.length)); StartCoroutine(numberSpeech.PlayFancyNumberAudio((int)distOff)); yield return(new WaitForSeconds(2.5f)); } else if (snapShotBallPos.x == 0) { //Put it right in the middle middleAudio.Play(); yield return(new WaitForSeconds(middleAudio.clip.length)); } yield break; }