
사건의 발단
魔法少女ノ魔女裁判 라는 일본 비주얼 노벨 게임을 발견했다. 단간론파 비슷한 느낌이다. 재밌어 보인다.
문제: 한글이 없다. 중국어는 있다.
일본어는 어느정도 할 줄 안다. 하지만 편하게 우리말로 하고 싶었다.
중국어를 한글로 바꾸기만 하면 되는 거 아니야? 이게 모든 삽질의 시작이었다.
Unity Bundle 파헤치기
Unity 게임의 텍스트는 .bundle 파일에 들어있다. 암호문 같다.
구글링 1시간 → UnityPy 라이브러리 발견.
import UnityPy
env = UnityPy.load("game.bundle")
for obj in env.objects:
if obj.type.name == 'TextAsset':
data = obj.read()
text = data.m_Script # 됐다!
성공. 근데...
Naninovel 포맷이라는 복병
# CharacterID
; 日本語原文
中文翻译
이게 뭐야?
검색 결과: Naninovel이라는 엔진이다.
;(세미콜론) = 일본어 주석- 그 아래 줄 = 실제 표시되는 텍스트
일본어 주석을 번역하면 중국어 대신 한국어가 나온다. 구조는 파악했다.
Google Translate 돌려보자
24개 스크립트 파일을 Google Translate API로 번역. 10분 완료.
게임 실행. 한글 나온다!
...근데 화면에 이상한 게 보인다.
<ruby="くびつ">首吊</ruby>り縄
루비 태그가 그대로 화면에 나온다.
목을 매는 밧줄이라고 써야 하는데 <ruby="くびつ">首吊</ruby>り縄 이게 그대로 나온다.
Ruby 태그와의 전쟁
정규표현식으로 태그를 제거했다.
def clean_ruby_tags(text):
import re
return re.sub(r'<ruby="[^"]*">([^<]+)</ruby>', r'\1', text)
<ruby="くびつ">首吊</ruby>り縄 → 首吊り縄
깔끔. 이제 번역하면 되겠네?
근데 번역 품질이 별로다. 기계적이다. 어색하다.
Qwen AI 투입 (로컬의 맛)
Qwen2.5-7B 모델 발견. RTX 4080에서 돌아간다.
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct",
device_map="auto",
load_in_8bit=True # VRAM 7GB
)
문맥을 줘봤다
이전 3개 대사를 context로 제공.
context = previous_lines[-3:] # 이전 3개 대사
prompt = f"""
이전 대사:
{context}
번역할 문장:
{japanese_text}
"""
왜 3개?
- 반말/존댓말 왔다갔다 안 하게
- 말줄임(...) 같은 거 제대로 처리하게
성능
RTX 4080 16GB 기준:
- 8비트 양자화: 문장당 1-2초
- 챕터 1 전체: 1.5시간
결과: 어색하지만 게임은 플레이 가능.
GPU 팬 소리가 비행기 이륙하는 소리 같았다.
배운 것
- 도구부터 찾아라
UnityPy 없었으면 바이너리 파싱부터 했을 것이다. 인생 낭비. - 문제는 부딪히면서 해결
Ruby 태그? 게임 켜보고 발견. 미리 알 수 없다. - 문맥이 중요하다
3개 대사 참고하니까 번역이 좀 낫다. 아주 조금. - 로컬 AI의 장점
무료다. 무제한이다. 전기세? 그건 나중 문제다.
다음 편: 로컬 모델은 한계가 있다는 걸 깨닫는 순간
'개발관련' 카테고리의 다른 글
| Unity 게임 번역기 개발기 #6: 최적화와 크로스플랫폼 (0) | 2025.10.19 |
|---|---|
| Unity 게임 번역기 개발기 #5: RPG 메이커? 그것도 된다 (0) | 2025.10.18 |
| Unity 게임 번역기 개발기 #4: 개발은 디테일이다 (1) | 2025.10.12 |
| Unity 게임 번역기 개발기 #3: 코드가 괴물이 되다 (0) | 2025.10.11 |
| Unity 게임 번역기 개발기 #2: 돈을 쓰기로 했다 (0) | 2025.10.10 |