ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Unity에서 여러 Scene으로부터 점수를 합산하여 내는 점수체계 C# Script 코드 쓰기
    CS/졸업 프로젝트(Duk to Me) 2023. 8. 16. 19:43
    반응형

     

      Unity 프로젝트에서 NPC와의 영어 회화 학습을 진행하기 위해 여러 Scene을 이어 붙여서 이 Scene들로부터 점수 정보를 합산하여 계산해내는 C# 코드를 새로 생성하여 작성하였다. ScoreDelivery.cs는 점수 정보 전달 역할만을 위한 코드이며 ScoreManager.cs는 최종 점수를 계산해서 DB로 점수 정보를 보내는 역할이다.

     

    public int scoreValue = 0; // ScoreManager로 보낼 점수 정보담는 변수
    
    private void RecognizeSuccessEventHandler(RecognitionResponse recognitionResponse)
    {
    	string transcript = recognitionResponse.results[0].alternatives[0].transcript;
    	string scriptPath = "Script.txt";
    	int scriptLineNumber = 0; // Specify the line number you want to compare
    
    	string[] scriptLines = File.ReadAllLines(scriptPath);
    	string scriptLine = scriptLines[scriptLineNumber];
    
    	bool matchFound = transcript.Trim().Equals(scriptLine.Trim(), StringComparison.OrdinalIgnoreCase);
    
    	if (matchFound)
    	{
    		float matchPercentage = 100f;
            	scoreValue = 100;
            	ScoreDelivery.SetSceneScore(scoreValue); // ScoreDelivery로 보내기
    		Debug.Log("Success!");
    		// Perform actions when a script line matches
    		InsertRecognitionResponseInfo(recognitionResponse);
    		PrintScore(matchPercentage);
    		Debug.Log($"Match Percentage: {matchPercentage}%");
    	}
    	else
    	{
    		float matchPercentage = CalculateMatchPercentage(scriptLine, transcript);
    		scoreValue = (int)matchPercentage;
            	ScoreDelivery.SetSceneScore(scoreValue); // ScoreDelivery로 보내기
            	Debug.Log("Try again!");
    		// Perform actions when no script line matches
    		InsertRecognitionResponseInfo(recognitionResponse);
    		PrintScore(matchPercentage);
    		Debug.Log($"Match Percentage: {matchPercentage}%");
    	}
    }
    
    private float CalculateMatchPercentage(string scriptLine, string transcript)
    {
    	string[] scriptWords = scriptLine.Trim().Split(' ');
    	string[] transcriptWords = transcript.Trim().Split(' ');
    
    	int matchingWords = 0;
    
    	for (int i = 0; i < scriptWords.Length && i < transcriptWords.Length; i++)
    	{
    		if (scriptWords[i].Equals(transcriptWords[i], StringComparison.OrdinalIgnoreCase))
    		{
    			matchingWords++;
    		}
    	}
    
    	return (float)matchingWords / scriptWords.Length * 100f;
    }
    
    private void PrintScore(float matchPercentage)
    {
    	if (Math.Abs(matchPercentage - 100f) < 0.0001f)
    	{
    		Debug.Log("Excellent!");
    	}
    	else if (matchPercentage >= 90)
    	{
    		Debug.Log("Great job!");
    	}
    	else if (matchPercentage >= 80)
    	{
    		Debug.Log("Well done!");
    	}
    	else if (matchPercentage >= 70)
    	{
    		Debug.Log("Good effort!");
    	}
    	else if (matchPercentage >= 60)
    	{
    		Debug.Log("Nice try!");
    	}
    	else
    	{
    		Debug.Log("Keep practicing!");
    	}
    }

     

    위의 코드는 Unity Google Speech API Asset(https://assetstore.unity.com/packages/tools/ai-integration/speech-recognition-using-google-cloud-vr-ar-mobile-desktop-pro-72625)에서 제공하는 GCSR_Example.cs 파일에서 프로젝트 필요에 맞춰 추가수정한 코드 부분이다. 음성인식이 성공했을 때 RecognizeSuccessEventHandler 안의 코드가 실행된다. scriptPath 변수 안에 넣은 파일명 안에 담긴 스크립트 내용과 음성 인식된 내용이 담긴 trascript 변수를 비교한 결과를 matchFound에 저장하여 참과 거짓의 결과에 따라, 참일 때는 점수를 100으로 지정하여 이를 ScoreDelivery로 보낸다. 거짓일 때는 CaculateMatchPercentage 안의 코드대로 transcript와 script의 내용을 trim을 이용하여 공백을 제거한 상태에서 서로 단어를 순서대로 비교하는 방법으로 정확도를 계산해서 100분위로 환산한 정확도 결과를 ScoreDelivery로 보낸다. PrintScore 는 Console 창에 점수별로 얼마나 잘한건지를 쉽게 알 수 있게 하기위해 추가하였다.

     

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ScoreDelivery : MonoBehaviour
    {
        public static int SceneScore = 0;
    
        public static void SetSceneScore(int scoreValue) {
            SceneScore = scoreValue;
        }
    
        public void NextonClick() { // next버튼 눌렀을 때 마지막 점수가 ScoreManager에 합산되도록 보내기
            ScoreManager.AddScore(SceneScore);
        }
    
    }

     

    점수를 보내기 위해 쓴 ScoreDelivery 코드이다. ScoreManager는 Scene에서 Next 버튼이 눌렸을 때 가장 마지막에 저장되어 있는 SceneScore 값을 ScoreManger로 보낸다. 그 전까지는 음성인식을 몇번을 하든지 가장 마지막에 갱신된 점수 정보만 보내진다.

     

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using PlayFab;
    using PlayFab.ClientModels;
    
    public class ScoreManager : MonoBehaviour
    {
        public static int totalScore = 0;
    
        public static void AddScore(int score)
        {
            totalScore += score;
        }
    
        public static int GetScore()
        {
            return totalScore / 6; // 씬의 갯수만큼 나눠서 평균 출력하기
        }
    
        // GetScore() method를 call하면서 PlayFab DB로도 scoreValue를 account별로 보내기
        public void HandleButtonClick()
        {
            int scoreValue = ScoreManager.GetScore();
    
            if (scoreValue <= 100 && scoreValue >= 80)
            {
                Debug.Log("Excellent!");
                Debug.Log($"Average Score: {scoreValue}%");
            }
            else if (scoreValue >= 70)
            {
                Debug.Log("Great job!");
                Debug.Log($"Average Score: {scoreValue}%");
            }
            else if (scoreValue >= 50)
            {
                Debug.Log("Well done!");
                Debug.Log($"Average Score: {scoreValue}%");
            }
            else if (scoreValue >= 0)
            {
                Debug.Log("Keep Practicing!");
                Debug.Log($"Average Scor: {scoreValue}%");
            }
    
            // Call the method to send the score to PlayFab
            SendScoreToPlayFab(scoreValue);
        }
    
        private void SendScoreToPlayFab(int score)
        {
            // Assuming you have already authenticated the player with PlayFab
    
            // Create a request to update the player's data
            UpdateUserDataRequest request = new UpdateUserDataRequest
            {
                Data = new Dictionary<string, string>
                {
                    { "score", score.ToString() }
                }
            };
    
            // Send the request to PlayFab
            PlayFabClientAPI.UpdateUserData(request, OnUpdateUserDataSuccess, OnUpdateUserDataFailure);
        }
    
        private void OnUpdateUserDataSuccess(UpdateUserDataResult result)
        {
            Debug.Log("Score successfully sent to PlayFab!");
        }
    
        private void OnUpdateUserDataFailure(PlayFabError error)
        {
            Debug.LogError("Failed to send score to PlayFab: " + error.ErrorMessage);
        }
    
    }

     

    ScoreDelivery로 부터 받아온 score 를 계속 합산하여 마지막 Scene에서 점수 결과 버튼을 클릭했을 때, HandleButtonClick Method에서 GetScore Method를 Call하여 Scene 만큼 나눠진 최종 점수 결과를 점수 대에 맞는 Console창의 메세지와 함께 구할 수 있다. 마지막에서는 PlayFab DB로 최종 점수를 튜플 형식으로 보내고 있다.

     

    반응형
Designed by Tistory.