2018年12月17日 星期一

替 Endless Space (萬艦穿星) 做的繁中漢化

最近一個月都沉浸在 Endless Space 2 的世界裡無法自拔。二代的遊戲內容已全面支援繁體中文,遊玩上的帶入感確實比起一代強烈得多。

一代雖然也有由玩家社群貢獻的中文漢化補丁,但簡體中文的部分比較完整,至於繁體中文的部分目前似乎只有一個 codebay.in 的繁中漢化包,而且只支援主程式,並不支援資料片 Disharmony。

上上週末突發異想,干脆自己跳進去嘗試補完一代繁中漢化的部分。雖然我還沒有任何遊戲漢化的經驗,但我知道 Endless Space 是用 Unity 開發的,這引擎我倒算熟悉。於是乎報紙捲一捲我就上山打虎去了。

原本預想的很單純 -- Endless Space 內的所有字串表都是以 XML 的格式獨立存放在遊戲目錄下,未有任何保護。而 Unity 自 3.x 版本起就已支援動態文字繪製 (Dynamic Font),所以我預期只要把遊戲中使用的 TTF/OTF 字型換成能支援繁中的開源字型 (DroidSans,思源或文泉驛等等) 然後把字串表都改成繁中內容就搞定了。沒想到馬上就體認到理想與現實的差距,原本預估一個週末完工的時程也膨脹到一個多禮拜...。以下開始血淚分享其中步驟。


在繼續往下說古前,列一下此次漢化作業過程中有使用到的工具:

  1. Unity Asset Bundle Extrator (UABE) - 目前要對 Unity 遊戲進行各種內容抽出/替換的首選工具,沒有之一。
  2. UnityEx - 戰鬥民族開發的工具,作用如同 UABE 但針對某些類型的內容 (如字型檔) 的抽換,比起 UABE 來的方便。
  3. BMFont - 給它 TTF/OTF 字型,以及所需要的文字,它幫你產生點陣字型 (Font Atlas)。
  4. bmfm - 為了此次漢化作業特別開發的小工具,可以把既有的兩組點陣字型 (BMFont 格式) 合併為一個。
  5. pcf2bmfont - 也是我特別為此次漢化作業開發的小工具,用來把國喬中文開源出的點陣字型 (PCF格式,Big5編碼) 轉換為 BMFont 的點陣字型格式。

我第一步嘗試的就是替換遊戲中的 TTF/OTF 字型。執行的方法為: 用 UABE 逐個開啟遊戲資料夾內的 sharedassetsN.assets 檔案,查找類型為 FontAsset 的項目 (忽略名為 "Arial" 的項目,那是 Unity 預設會包進遊戲資料的字型,實際上未使用)。最終會在 sharedassets2.assets 這個檔案中找到它們。所以由此確認字型藏在這裡面。特別提一下,sharedassets 彼此之間是有相依關係的,而 UABE 在開啟一個 asset bundle 時會自動把相依的其它 asset bundle 也載進來。所以你會在很多個 sharedassetsN.assets、甚至是 resources.assets 裡也發現這些字型被列在裡面。判斷的方法是注意 File ID 那個欄位,其值是 0 的話才代表該檔案存在於你目前開啟的 asset bundle。非 0 的值都代表是靠相依性載入的,配合左上角功能選單 "View" / "Dependencies" 可查出該 File ID 究竟是儲存於外部的哪一個 asset bundle。



鎖定字型位置之後,接下來要抽換 TTF/OTF 的內容。這個動作在 UABE 中無法直接進行。因為字型檔的具體內容是夾在 asset 內的一部分,由某個 offset 開始後的指定長度。懂行的朋友配合 UABE "View Data" 給的提示就能在匯出的 dump 上配合 shell 中的 dd 指令來進行抽換,或是寫一個簡單的 python script 來用。但這一步其實改用 UnityEx 來進行抽換會比較方便: 首先你把 sharedassets2.assets 複制到一個空的目錄,然後在 UnityEx 的界面中打開它,選擇要抽換的 TTF/OTF 檔案,然後滑鼠右鍵選 Export Selected。此時在那個目錄下會有一個資料夾創出來,裡面就是該字型檔。接著你把那個檔案代換掉 (檔名需一致),回到 UnityEx 界面中按上面靠中間的那個 "Import all files" 按鈕,它就會把你改過的檔案縫回去 asset 檔裡。



施工完再進入遊戲 (字串表中要先故意把幾個字串改成中文來測試,另外注意字串表檔案需以 UTF-8 格式儲存、檔首不可有 BOM) 發現還是無法顯示中文,踢到第一個鐵板。這說明 assets 中雖有包含 TTF/OTF 字型,但實際運行時不會使用。因此抽換 TTF/OTF 這條路是無效、根本不必做的。如此一來這個遊戲必然是使用 Bitmap Font (或稱 Font Atlas) 的方法來顯示字型。

再回到 UABE 列出的 sharedassets2.assets 內容裡翻翻找找,會發現總共有五個 Font Asset -- 分別名為 "SmallText", "NormalText", "NormalTextLight", "LargeText", "HugeText"。然後巧的是每一個名字都搭配存在一個 TextAsset (文本檔案)、以及 Texture2DAsset (圖檔)。抽出後一看果不其然就是 Font Atlas,而且格式還挺眼熟 -- 就是 BMFont 這個軟體產出的格式 -- 一份 XML 配上一張 2D 圖。
(附註: TextAsset 的文本內容要透過 UABE 的 Plugins / Export to .txt 來匯出,而 Texture2DAsset 的圖檔內容亦為 Plugins / Export to .png 來匯出)


所以接來的方向就清楚了 -- 要針對這五個尺寸產出新的 Font Atlas,裡面要含有所有遊戲中會出現的文字。這邊會有個雞生蛋蛋生雞的問題,因為此時遊戲內文的翻譯還不齊,所以勢必是要先隨便選一些字、把整個製程先打通之後,再回頭去搞翻譯,翻完後再跑一次整個流程以製作最終版。

製作 Font Atlas 可透過 BMFont 這個免費工具來協作。然後還得先搞一套沒有版權問題的字型。雖然我沒有營利的行為,但是這年頭律師比老師還多,在版權方面保守一點決不會錯的。推薦文泉驛微米黑、或是早期 Android 系統內建的 Droid Sans。不知為何 BMFont 在產出小尺寸字型時,選用 TTF 的效果會比 OTF 好很多,然而新的 Android 使用的開源字體 Noto 已都是 OTF 的格式了,效果不理想。

下面簡略講一下 BMFont 內的操作方式:

先到 Options / Font Settings 裡面, "Add font file:" 那邊指定你下載的字型,然後在上面一行 "Font:" 即可選到你下載的字型。接下來只要調 "Size (px):" 那欄就好。從抽出的那五個 XML 文件中的 lineHeight 可以得知,五個字型對應的 pixel size 分別是 (由小到大):  13px, 16px, 16px, 23px, 45px。所以先設成 13,然後整個流程要重複 4 次 (16px 的統一做一次就好)。

再到 Options / Export Options 裡面,Texture 底下的 Width 跟 Height 都先設 1024、 Bit Depth 選 32 bits。下方 "Presets" 處選 "White text with alpha";"Font Descriptor" 選 XML、"Textures" 選 png。



都設定完畢之後,透過 "Edit / Select chars from file" 功能,讀入一個盡可能完整包含遊戲中所有文字的文字表。測試時可隨便找些新聞 copy paste 到文字檔讓它讀。等最終我們翻譯搞定之後,當然就是要它去讀翻譯好的那些 XML 字串表。載入後請手動把右側最上方的 "000000 - Latin + Latin Supplement" 前面的方框多按幾次讓它變全空,我們不要這區段內的文字,因為最終我們還是會把產出的 Bitmap Font 與遊戲原本的那份 Bitmap Font 合併,而遊戲裡那份原本就有包含這個區段的文字了。

最後,先透過 Options/ Visualize 預覽一下匯出的結果,注意上方的視窗標題必需要顯示 1/1 (代表只有輸出一張圖),若是 1/2 或更高的數字,代表一張圖裝不下,要調整 Export Options 中 Texture Width/Height 的值來修正。此值必需是 2的次方倍,因此若 1024x1024 裝不下,下個可以試試 2048x1024、或 2048x2048。通常 Large 跟 Huge 才會需要這樣調整。預覽沒問題之後就按 "Options / Save bitmap font as ..." 來匯出 Font Atlas。

接著我們要嘗試把產出來 Bitmap Font 跟遊戲中原本的 Bitmap Font 進行合併,這部分靠人工無法完成,所以要靠上面提到的小工具 bmfm 來進行,執行檔可直接由 gitlab 上抓下。它是命令列的工具,因此要用以下指令執行:

bmfm.exe -W 1024 -H 512 -n SmallText_0.png -x SmallText.txt SmallText_ORG.txt SmallCh.fnt
bmfm.exe -W 1024 -H 1024 -n NormalText_0.png -x NormalText.txt NormalText_ORG.txt NormalCh.fnt
bmfm.exe -W 1024 -H 1024 -n NormalTextLight_0.png -x NormalTextLight.txt NormalTextLight_ORG.txt NormalCh.fnt
bmfm.exe -W 1024 -H 1024 -n LargeText_0.png -x LargeText.txt LargeText_ORG.txt LargeCh.fnt
bmfm.exe -W 2048 -H 2048 -n HugeText_0.png -x HugeText.txt HugeText_ORG.txt HugeCh.fnt

(上述假設你抽出來的五個 TextAsset 分別為 "SmallText_ORG.txt", "NormalText_ORG.txt", 以此類推... 而 BMFont 製作出來的是 "SmallCh.fnt", "NormalCh.fnt", ...)

合併完的結果大概就是長這個樣子:


最後,再透過 UABE 的協助,把這 10 個檔案塞回去 sharedassets2.assets 就大功告成。塞 TextAsset 的方式是先選 TextAsset,然後透過 "Plugins / Import from .txt" 來匯入。而 Texture2DAsset 則是 "Plugins/Edit" 再透過其面板上的 "Load" 按鈕來匯入。

把最終得到的 sharedassets2.assets 放回遊戲目錄,然後試著在 XML 字串表中隨便把主選單上的文字改成新聞中有出現的字來測試。發現可以顯示。

但是這樣的結果還是有個地方讓我超在意的,因為 Endless Space 裡雖然有五種字型 (其中兩種大小相同,因此只有四個尺寸),但是遊戲中 90% 都只有最小的那兩個字型,也就是 13px 跟 16px。在這麼低的解析度下,無論怎麼調整 BMFont 的參數,中文字都會看起來糊糊的,讓我超介意。後來我轉念想到更久以前的點陣字時代,通行的兩種尺寸就是 16x15 以及 24x24。在網上一陣訪查之後,發現國喬中文系統後來有把它的點陣字開源釋出使用,我最終在 NetBSD 的 packages 庫裡總算是把這古董給挖了出來啦 (kcfonts)

下載完解壓後,可發現 kcXXX.pcf.gz 檔案數個,再用 gzip (7-zip也可解) 解開得到 kcXXX.pcf。是比較舊的 PCF 格式字型檔,並且內部採取的編輯是早年通行的 Big5 而非 unicode。所以我又另外寫了一個工具把 PCF 轉換為與 BMFont 相容的字型,即上述提到的 pcf2bmfont。如此一來,就能跟原本的流程接上軌了。

以上就是整個工程的經過,後續我就只是把內容翻譯完,然後再照著上述流程跑一次。實在沒想到真正花時間的還是在翻譯上...


附註: 最終的成果裡,13px、23px、45px 這三個尺寸是用 BMTFont + 文泉驛微米黑中文字體的搭配。而只有 16px 才是使用國喬中文的點陣字。

1 則留言:

  1. 從巴哈那邊看到這篇中文化,真的非常感謝!!
    已安裝成功,這遊戲真的很經典好玩啊!!!

    回覆刪除