https://www.youtube.com/watch?v=VNhzMEsy7xc
Localization 패키지, Addressables 패키지 설치
Edit > Project Settings > Localization > ( _Locale 폴더 새로 만들어서) Create
Locale Selectors
Command Line Locale Selector : 커맨드로 언어 바꾸는 거
System Locale Selector : 시스템에서 언어 설정돼있는거
Specific Locale Selector : 이 부분을 건드려야 된다
Add Locale > 원하는 언어 선택 > (_Locale 폴더에) Add Locales
Specific Locale Selector를 골랐던 언어만큼 더 추가하고 Locale Id 설정
Project Locale Identifier
이 프로젝트에서 기본이 될 언어는 무엇인지
Window > Asset Management > Localization Tables > New Table Collection (_Locale 폴더 안에 Tables 폴더 새로 만들어서)
New Entry > Key는 딕셔너리의 key라고 생각하고 쓰면 된다
(필수는 아님) 다 채웠으면 위쪽의 중괄호 두개로 감싸져 있는 기호 클릭하면 metadata(이 데이터가 무슨 데이터인지 코멘트) 수정
다국어화할 텍스트 오브젝트에 Localize String Event 컴포넌트 (Localize 이벤트가 실행되면 문자열을 해당하는 언어로 바꿔줌) 추가
(컴포넌트 우측 상단 점 세개 눌러서 Localize 눌러도 추가됨)
String Reference > 'None (String)' 클릭 > 텍스트에 해당하는 String 선택
Update String > 해당 오브젝트의 Text 혹은 TextMeshPro 할당 > (TextMeshPro 기준) No Function 클릭 > TextMeshProUGUI > text
Runtime only를 Editor And Runtime으로 바꾸면 게임 안 켜고도 바로 보임
게임 켜보면 게임 뷰 우측 상단에 언어 설정이 생기고, 바꾸면 언어 바꿔서 볼 수 있다.
컴포넌트에서 직접 Table Entry를 추가할 수도 있다.
String Reference가 안 보여서 직접 찾아가야 한다면 (버전마다 다름)
Preferences > Localization > Asset Search Picker, String Search Picker 체크 해제
Update String
언어 바꿀 때 바뀌는 텍스트 설정
Locale Manager 오브젝트를 만들고
public class LocaleManager : MonoBehaviour
{
bool isChanging;
public void ChangeLocale(int index)
{
if (isChanging)
return;
StartCoroutine(ChangeRoutine(index));
}
IEnumerator ChangeRoutine(int index)
{
isChanging = true;
yield return LocalizationSettings.InitializationOperation;
LocalizationSettings.SelectedLocale = LocalizationSettings.AvailableLocales.Locales[index];
isChanging = false;
}
}
스크립트 붙인 뒤에
버튼의 OnClick()에 LocaleManager.ChangeLocale 할당
언어에 따라 스프라이트, 텍스처도 바뀌게 하고 싶을 때 사용
(영상 15:45부터)
Window > Asset Management > Localization Scene Controls
(영상 19:20부터)
Entry에서 Smart를 체크하고 Edit을 누른 뒤
Local Variables를 바로 추가하거나
Create > Localization > Variables Group를 만들고 Local Variables에 Nested Variable Group을 추가한 뒤
"{global.player-name}가 접속했습니다" 와 같이 적용
Preview를 누르면 어떻게 출력될지 보여줌
(영상 22:32부터)
(영상 30:49부터)
가져오는 예시
Locale currentLocale = Localization.SelectedLocale;
nameText.text = LocalizationSettings.StringDatabase.GetLocalizedString("MyTable",talker.talkerName,currentLocale);
중간에 언어를 바꾸면 이미 불러온 데이터가 갱신되지 않는 경우가 생길 수 있으니
private void Start()
{
LocalizationSettings.SelectedLocaleChanged += OnChangeLocale;
}
로 이벤트를 할당한다
Table 가서 Extension > Csv Extension 추가 > Save
(Google Sheets Extension으로 온라인 연동도 가능. 보안 문제가 있기 때문에 매뉴얼 보면서 진행해야함)
Open으로 불러오기도 가능

드롭 다운 눌렀더니 못생긴 하얀색이 다시 튀어나오고
슬라이더 늘렸더니 살짝 뚱뚱

게임 시작하고 드롭다운 연 다음 템플릿 바꾸니까 모습 안 바뀌고
아래거 바꿔야 바뀌는데
이거 뭔가 스크립트랑 연결돼서 템플릿을 아이템들에 적용시키는듯?

만지작 거려봤는데 바꿔지질 않아서
https://www.youtube.com/watch?v=FdtqeLLExjA
유튜브 수강했는데 여긴 디자인 쪽 치중해서 알려주는게 아니라 기본만 훑고 있었다

레퍼런스 게임에서 드롭다운 연 디자인을 유튜브 뒤져서 찾아냄
https://youtu.be/cD5rlpF1ZfE?si=SrSQYnbEkbjTimYU&t=30

유니티 매뉴얼도 소용 없어서 더 만지작 거리다 이쯤에서 타협하기로
https://www.youtube.com/watch?v=VNhzMEsy7xc
생각보다 오래 걸릴듯

이렇게 관리하는게 맞는지 모르겠음.
애셋 사서 관리하거나 스크립트 짜서 csv파일로 관리하는게 맞지 이건 너무 기초적인 수준인듯
텍스트 한 두개 있을때야 막무가내로 번역하는게 가능하지 점점 늘어나면 답도 없을듯

언어 개수도 뇌절하지 말고 이 그래프에 있는 것들이랑 번체, 한국어 정도만 추가하자.

그냥 csv 파일 편집한 다음에 import하면 되는구나

그래 이렇게 하면 그나마 받아들일만하지 이상한 인터페이스 들이밀면서
이걸로 현지화하셈 ㅋㅋ 이러니까 당황스러웠다
이러면 gpt한테 번역 맡긴 다음에 데이터만 import하면 바로 번역 완료
여기서 table로 데이터 분류하고 C# 스크립트나 vba같은 걸로 어떻게어떻게 잘 관리하는게 프로젝트 커졌을 때의 정석이고
더 편하게 하고 싶으면 애셋 사는거고 그런거겠지
https://www.youtube.com/watch?v=a9lkBiTiD7M
구글 스프레드시트로 번역 자동화하는 방법도 있고 (기계 번역이라 수준은 그닥이겠지만)

UI 디자인할 때 버튼 크기를 텍스트보다 크게 만들고 그 안에 텍스트를 넣는 이유가 있었다
이러면 임이랑 종을 눌러야 게임이 꺼지고 게랑 료 누르면 아무 반응도 안할거임
근데 뭐 굳이 이거까지 신경쓰고싶지 않아서 게임 종료가 아니라 종료로 바꾸자

? 드롭다운은 어케 번역함
우측 점 세개에 Localize 버튼이 없는데?
https://discussions.unity.com/t/how-to-localize-dropdown-menu/941336
https://docs.unity3d.com/Packages/com.unity.localization@1.4/manual/LocalizedPropertyVariants.html
또 매뉴얼을 읽어야되는구나 어지럽다
https://sonsazang.tistory.com/18
여기에 있는거 복붙해도 될듯

되긴 하는데
설정해놨던거 save 해놨다가 시작할 때 그거 기반으로 언어 보이도록 해야됨

ㅇㅋ 한 번 써봄
https://docs.unity3d.com/Manual/AudioMixerSpecifics.html

왜 이거 쓰라고 한 건진 알겠는데...
지금 쓰고 싶진 않다
나중에 바꾸자
슬라이더가 비활성화 돼있어도 value 값을 가져올 수 있는가?
Slider.value를 읽거나 설정할 수 있습니다.OnValueChanged)가 동작하지 않는다는 점에 유의하세요.비활성화돼있으면 awake랑 start 둘 다 실행 안되지?
아니요! 비활성화된 오브젝트의 경우 Awake는 호출되지만, Start는 호출되지 않습니다.
씬 시작할 때 bgm과 sfx의 AudioSource를 playerpref에 저장된 값으로 초기화 (soundmanager.cs)
메뉴 열어서 슬라이더 활성화될 때 playerpref에서 값 가져오기 (menumanager.cs)
슬라이더 조절하면 값을 playerpref에 저장하고 해당되는 AudioSource의 Volume을 조절 (soundmanager.cs)
메뉴 껐다 키는 건 GameManager.cs에서 esc 입력 받아서 SetActive 조절
지금은 전부 프리팹화해놓은게 아니라서 씬마다 일일이 다 돌아다니면서 sfx Source랑 bgm Source 할당해줘야 하는데,
나중엔 씬 하나에서 맵만 해당되는 파일 불러와서 해결할거라 ㄱㅊ
애초에 생산성 좋게 만들어놨으면 좋았겠지만
두번째로 만들어보는 게임이니까 어쩔 수 없지
씬 돌아다니면서 할당해줘야할 거
1. soundmanager에 audiosource 할당
2. menumanager에 slider 할당
3. GameManager에 MenuCanvas 할당하고 MenuCanvas는 비활성화
하려고 했는데 미친짓이라는 걸 깨달아버림
이러면 어딘가에서 무조건 실수함
전부 다 묶은 오브젝트 하나 프리팹화한 다음에 그걸 각 씬에 다시 넣어주는게 정신 건강에 이로울 것 같다.
프리팹화는 나중에 문제되면 풀면 되는데 왜 꺼려했던거임
이러면 해야 될 일이
각 씬 돌아다니며
0. player 및 각종 중요한 오브젝트 들어있는 ManagerCoillection 프리팹을 기존 오브젝트와 교체하고
1. GameManage에서 Next Map Index 수정
2. SoundManager에서 AudioClip 할당
3. Player bpm, smooth Intensity 수정
4. Virtual Camera Follow 재할당
모든 맵 돌아다니면서 테스트 완료. 음량 조절 정상적으로 됨.
public void QuitGame()
{
Debug.Log("게임 종료");
UnityEngine.Application.Quit();
}
로그는 찍히는데 게임 종료가 안되는 이유
Unity 에디터에서 Application.Quit()을 호출하면 실제로 게임이 종료되지 않습니다. 이는 Unity 에디터에서 종료 동작을 테스트할 수 없도록 의도적으로 제한한 것입니다. 빌드된 실행 파일에서는 정상적으로 작동합니다.
public void QuitGame()
{
Debug.Log("게임 종료");
#if UNITY_EDITOR
UnityEditor.EditorApplication.isPlaying = false; // 에디터 플레이 모드 종료
#else
Application.Quit(); // 빌드된 실행 파일에서는 정상적으로 종료
#endif
}
Unity 에디터에서 게임 종료를 테스트하려면, UnityEditor.EditorApplication.isPlaying을 사용해 플레이 모드를 종료해야 합니다.
public void SetDebugMode(bool isDebug)
{
debugText.gameObject.SetActive(isDebug);
}
스크립트로 하려고 했는데

토글 onchanged 이벤트에 이거 달면 굳이 스크립트 만들 필요 없었다.
해놓고도 왜 안되지? 했는데 게임 켜놓고 프리팹 수정 hierarchy에서 작업하고 있어서 그랬고,
게임 종료했다가 다시 켜면 멀쩡히 SetActive() 호출해줌.
private void DebugText()
{
if (debugText == null) return;
Debug.Log("디버그 불러왔는데요");
이거 debugText 비활성화했는데 왜 log가 찍히는거?
debugText가 비활성화된 상태여도, 해당 오브젝트가 참조된 상태라면 코드에서 접근하여 값을 읽거나 메서드를 호출하는 것이 가능합니다. Unity에서 비활성화된 상태는 렌더링 및 업데이트 루프에서 제외될 뿐, 메모리 상에서 여전히 존재하므로 null이 아닙니다.
private void DebugText()
{
if (debugText == null) return;
Debug.Log("Check1");
debugText.text =
"bpm : " + bpm + "\n" +
(생략)";
Debug.Log("Check2");
}
check1이랑 check2 잘만 로그 찍히는데 text 업뎃 안되는거임?
할당 풀었다가 다시 할당하니까 멀쩡히 잘 됨. 얼탱이 없네
고양이 소리 하나만 하면 재미가 없어서 고양이를 고르면 6개 중에서 하나가 랜덤으로 재생되게 하고 싶음
player 아래에 자식 오브젝트 달아둔 다음에 오디오 소스 주렁주렁 달아놓으면 되지 않을까
자식 오브젝트 이름은 드롭다운 이름이랑 같게 할 수가 없구나 현지화 때문에
그럼 인덱스로 하면 되겠지
선택지마다의 오디오 소스가 담겨있는 게임 오브젝트들을 player의 배열에 넣어놓고
게임 오브젝트들에 있는 모든 오디오 소스를 바꿔끼면서
설명 포기 살짝 귀찮

private void hitSoundPlay()
{
myAudioSource.clip = hitSound.RandomHitSound();
myAudioSource.Play();
}
이게
public class HitSound : MonoBehaviour
{
public AudioClip[] hitSounds;
public AudioClip RandomHitSound()
{
int index = Random.Range(0, hitSounds.Length);
return hitSounds[index];
}
}
이걸 호출한다

아 잠깐만 바꿨던거 적용이 안돼서 왜 안되나 했더니 프리팹 안에 프리팹을 넣은게 아니라 씬에 있던걸 한꺼번에 넣은거라 player에서 수정한게 collections에 적용이 안됐음 이러면 player하고 관련된거 전부 다 초기화하고 다시 해야되는건데 어지럽다
어쩔 수가 없다 player 프리팹은 버리고 collections에 있는걸로 다시 가자
이게 제일 적게 바꾸는 길
어차피 나중에 각 씬에 있는 데이터 다 버리고 json 파일에 metatdata로 넣어버릴거라 ㄱㅊ

똑같은 함수가 위에도 있고 아래에도 있는데 위에 있는걸 골라야 매개변수를 넘겨준다
개고생해서 만든거 치고 살짝 심심하긴 한데
확장성 있게 만들게 된거니까 됐다...

Create > 3D Object > Text
Localize String Event 컴포넌트 추가하고 테이블에 key 추가한 후에
Update String에 TextMeshPro - Text 컴포넌트 할당하고 TextMeshPro.text 이벤트 추가
esc 누르면 일시정지 효과, 다시 누르면 3초 뒤에 게임 재시작
해상도 변경 추가
씬 전환 효과