ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 영어 기능 지원#1
    Galaxy Ball/6. 기타 수정 + 추가 기능 2025. 1. 10. 20:47

    이번엔 영어 기능을 지원해보도록 하겠다. 사실 이 게임을 외국인이 할까 싶지만

    공부용으로라도 배워보도록 하자

     

     

    우선 설정창에 언어를 제어할 두 국가의 국기를 버튼으로 넣어주었다.

    당연히 태극기를 누르면 한국어, 영국국기를 누르면 영어가 나오도록 해줄것이다

     

      public void SaveIsisenglish()
        {
            if (isenglishCache != isenglish)  // 값이 변경된 경우에만 저장
            {
                PlayerPrefs.SetInt("isenglish", isenglish ? 1 : 0);
                PlayerPrefs.Save();
                isenglishCache = isenglish;  // 캐시 업데이트
            }
        }

     

    가장 먼저 StageGameManager에서 영어 번역여부를 결정해줄 bool타입 isenglish 변수를 추가해주었다

     

     

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using TMPro; // TextMeshPro 네임스페이스 추가
    
    public class TranslateUI : MonoBehaviour
    {
        private TMP_Text[] allTexts;
        private StageGameManager stageGameManager;
    
        // 번역 딕셔너리: 원본 텍스트 -> 영어 번역
        private Dictionary<string, string> translationDictionary = new Dictionary<string, string>()
        {
            { "크레딧", "Credit" },
            { "돌아가기", "Back to Menu" },
            { "스토리모드", "Story Mode" },
            { "연습모드", "Practice Mode" },
            { "무한모드", "Endless Mode" },
            { "뒤로가기", "Back" },
            { "새 게임", "New" },
            { "이어하기", "Con\ntinue" },
            { "기존 저장정보를 덮어씁니다.\r\n계속하시겠습니까?", "This will overwrite your existing save." },
            { "스토리모드를 먼저 플레이 후\r\n즐기시는 것을 추천 드립니다.", "Try story mode first\r\nfor the best experience" },
            { "계속하기", "Resume" },
            { "재시작", "Retry" },
            { "스테이지 맵", "Stage Map" },
            { "메인 메뉴", "Main Menu" },
            { "일시 정지", "Pause" },
            // 필요한 만큼 추가
        };
    
        // 영어 -> 한국어 딕셔너리 생성
        private Dictionary<string, string> reverseTranslationDictionary;
    
        private void Start()
        {
            // 역번역 딕셔너리 생성
            reverseTranslationDictionary = new Dictionary<string, string>();
            foreach (var kvp in translationDictionary)
            {
                reverseTranslationDictionary[kvp.Value] = kvp.Key;
            }
        }
    
        private void Update()
        {
            stageGameManager = FindAnyObjectByType<StageGameManager>();
    
            // 현재 씬의 모든 TextMeshPro 객체 가져오기
            allTexts = FindObjectsOfType<TMP_Text>();
    
            // 번역 조건 확인
            if (stageGameManager.isenglish)
            {
                TranslateAllTextsToEnglish();
            }
            else
            {
                TranslateAllTextsToKorean();
            }
        }
    
        void TranslateAllTextsToEnglish()
        {
            foreach (var text in allTexts)
            {
                // 텍스트 정규화
                string normalizedText = text.text.Replace("\r\n", "\n").Trim();
    
                // 딕셔너리의 키도 정규화하여 비교
                foreach (var kvp in translationDictionary)
                {
                    string normalizedKey = kvp.Key.Replace("\r\n", "\n").Trim();
    
                    if (normalizedKey == normalizedText)
                    {
                        text.text = kvp.Value; // 영어로 변환
                        break;
                    }
                }
            }
        }
    
        void TranslateAllTextsToKorean()
        {
            foreach (var text in allTexts)
            {
                // 텍스트 정규화
                string normalizedText = text.text.Replace("\r\n", "\n").Trim();
    
                // 역번역 딕셔너리의 키도 정규화하여 비교
                foreach (var kvp in reverseTranslationDictionary)
                {
                    string normalizedKey = kvp.Key.Replace("\r\n", "\n").Trim();
    
                    if (normalizedKey == normalizedText)
                    {
                        text.text = kvp.Value; // 한국어로 변환
                        break;
                    }
                }
            }
        }
    }

     

    우선 스토리에 쓸 번역말고 UI를 번역해줄 코드이다. 

    텍스트의 양이 많다면 이렇게하지 않겠지만 양이 그렇게 많지 않은 관계로 딕셔너리에 원본 텍스트와

    번역할 텍스트를 한쌍으로 넣어주었다

     

    그리고 update문에서 isenglish(번역여부)가 참이라면

    TranslateAllTextsToEnglish 메서드를 이용하여 번역이 이뤄진다. 

    물론 반대의 경우에는 TranslateAllTextsToKorean 메서드가 실행되어 반대로 번역된다

     

    근데 왜 하필 최적화를 하면서 그렇게 배척했던 Update문을 사용해야 하는것일까?

     

     

    문제는 이것 때문이다. 일시정지를 했을 경우 timescale을 0으로 지정하여 게임속 시간이 멈추게 된다

    하지만 여기서 Fixedupdate를 쓰게 되면 timescale의 영향을 받는다고 한다

     

    그래서 동적으로 움직이는 update문을 사용하는것이다.

    게다가 이건 물리계산 같은게 들어가는게 아니기 때문에 update문을 사용하더라도 큰 부담이 없을것이다

     

     

     

    UI 번역이 잘 이뤄지는것을 확인할 수 있다. 물론 모든 씬마다 해당 스크립트를 부착해주는것을 잊지 말자

     

     

    UI 부분을 전부 업데이트 했다면 다음에 할것은 적 유닛 정보창!

    이걸 어떻게 하나하나 번역을 해야하나...고민을 하다

     

     

    그냥 영어용 프리팹을 전부 다시 만들어주었다. 너무 노가다가 아닌가 싶을 수 있지만

    저걸 번역할바엔 이렇게 만드는게 훨씬 시간이 절약된다

     

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ShowEnemyInfo : MonoBehaviour
    {
        public GameObject[] KEnemyInfos;
        public GameObject[] EEnemyInfos;
    
        public Transform canvasTransform;
    
        void Start()
        {
            StageState stageState = FindObjectOfType<StageState>();
            StageGameManager stageGameManager = FindObjectOfType<StageGameManager>();
            float stageClearID = stageGameManager.StageClearID;
    
            // KEnemyInfos 또는 EEnemyInfos 배열을 선택
            GameObject[] activeEnemyInfos = stageGameManager.isenglish ? EEnemyInfos : KEnemyInfos;
    
            foreach (GameObject enemyInfo in activeEnemyInfos)
            {
                if (enemyInfo != null)
                {
                    string enemyInfoName = enemyInfo.name;
                    if (enemyInfoName.Length >= 2)
                    {
                        // 이름 뒤의 두 자리 숫자를 추출
                        string idString = enemyInfoName.Substring(enemyInfoName.Length - 2);
    
                        // 숫자로 변환
                        if (int.TryParse(idString, out int enemyID))
                        {
                            if (enemyID == StageState.chooseStage)
                            {
                                InstantiateEnemyInfo(enemyInfo);
                                gameObject.SetActive(false);
                                break; // 일치하는 항목을 찾으면 루프 종료
                            }
                        }
                    }
                }
            }
        }
    
        void InstantiateEnemyInfo(GameObject enemyInfo)
        {
            GameObject instantiatedInfo = Instantiate(enemyInfo, Vector3.zero, Quaternion.identity);
            instantiatedInfo.transform.SetParent(canvasTransform, false);
    
            RectTransform rectTransform = instantiatedInfo.GetComponent<RectTransform>();
            if (rectTransform != null)
            {
                rectTransform.anchoredPosition = Vector2.zero;
            }
        }
    }

     

    그리고 적 정보창을 조건에 맞춰 출력시켜주는 스크립트에 들어가

    프리팹을 저장하는 배열을 하나 더 만들어 영어용으로 넣어준뒤 isenglish 스위치 여부에 따라

    가져오는 프리팹을 다르게 해주면 된다

     

     

     

     

    그리고 번역의 가장 핵심이자 제일 번역해야 할 양이 많은 스토리 대사.

    하지만 이것도 어렵지 않다

     

    public class ShowText : MonoBehaviour
    {
        public TextAsset KJsonFile;
        public TextAsset EJsonFile;
    
        StageGameManager stageGameManager;
    
        void Awake()
        {
            stageGameManager = FindAnyObjectByType<StageGameManager>();
            ChatBox.SetActive(true);
    
            // stageGameManager.isenglish 값에 따라 JSON 파일 선택
            TextAsset selectedJsonFile = stageGameManager.isenglish ? EJsonFile : KJsonFile;
    
            if (selectedJsonFile != null)
            {
                try
                {
                    var json = selectedJsonFile.text;
                    chats = JsonConvert.DeserializeObject<List<Chat>>(json);
                }
                catch (JsonReaderException e)
                {
                    Debug.LogError("Failed to parse JSON: " + e.Message);
                }
            }
        }

     

    실질적으로 Json파일에서 텍스트를 가져와 출력시켜주는 ShowText 스크립트에 가서

    상황에 따라 Json파일을 바꿔주는 selectedJsonFile 변수를 만들어 isenglish 여부에 따라 값을 다르게 받아주면 된다

     

    여기서 E 혹은 K JsonFile은 당연히 번역본, 원본이다

     

     

    그리고 번역본 Json 파일을 영어로 수정해주면 된다. 우선 임시로 맨 위 3개만 수정해주었다

     

     

    오... 잘 나오는것을 확인할 수 있다. 

    이제 전부 번역만 해주면 된다

     

    [
       {
          "id":1,
          "textWithDelay":[
             {
                "text":"Hi",
                "delay":0.05
             },
             {
                "text":"Im Developer",
                "delay":0.05
             },
             {
                "text":"......",
                "delay":0.12
             },
             {
                "text":"...Why? Not what you expected?",
                "delay":0.05
             },
             {
                "text":"You thought developers don't appear in the game themselves?",
                "delay":0.05
             },
             {
                "text":"Well... it's my game, can't I show up a little?",
                "delay":0.05
             },
             {
                "text":"Later, even if you want to see me, it might be hard, so take a good look now~",
                "delay":0.05
             },
             {
                "text":"So, what are we going to do from now on?",
                "delay":0.05
             },
             {
                "text":"If you came to play the game, I need to teach you how to play, right?",
                "delay":0.05
             },
             {
                "text":"Tutorial... no, let's start by learning how to walk! It's not that hard.",
                "delay":0.05
             },
             {
                "text":"Come on~ lightly scroll the screen once.",
                "delay":0.05
             },
             {
                "text":"   ",
                "delay":0.05
             },
             {
                "text":"   ",
                "delay":0.05
             },
             {
                "text":"   ",
                "delay":0.05
             },
             {
                "text":"See? Simple, right? You can move with just one finger~",
                "delay":0.05
             },
             {
                "text":"   ",
                "delay":0.05
             },
             {
                "text":"   ",
                "delay":0.05
             },
             {
                "text":"   ",
                "delay":0.05
             },
             {
                "text":"Alright, stop now.",
                "delay":0.05
             },
             {
                "text":"Don't wander around too much and then complain you didn't hear the explanation properly.",
                "delay":0.05
             },
             {
                "text":"Let me explain where you are.",
                "delay":0.05
             },
             {
                "text":"Right now, you're in my space, shared with 194 other friends besides you.",
                "delay":0.05
             },
             {
                "text":"Everyone looks different, but they're all my creations, so play nice!",
                "delay":0.05
             },
             {
                "text":"Let's see... now I need to give you a task.",
                "delay":0.05
             },
             {
                "text":"Alright then... your first mission as a developer is...",
                "delay":0.05
             },
             {
                "text":"To find a yellow ball with a red star in the middle!",
                "delay":0.05
             },
             {
                "text":"That's really it. Simple, right?",
                "delay":0.05
             },
             {
                "text":"Since it's the first time, I'll even show you an image below as a special case.",
                "delay":0.05
             },
             {
                "text":"See the bottom left? Just find something that looks exactly like this.",
                "delay":0.05
             },
             {
                "text":"Go ahead and look around to find it.",
                "delay":0.05
             }
          ]
       },
     
     ..............

     

    이런식으로 하나하나 전부 번역해준다. 물론 챗GPT의 도움을 받았다^^

     

     

     

     

Designed by Tistory.