2012年10月13日 星期六

[好文推薦] Unity中的中文顯示(一):你好,Unity



作者:死貓@indiegm
原文出處:http://www.chinavr.org/article/unity/2009-04-21/88.html

前言:之前有朋友發信來問如何在 Neoaxis 中顯示中文,當時答應寫篇教程放上來。後來忙於I'm Lulu King!的製作,就給擱下了。等 I'm Lulu King! 提交後,卻又累得連打開 Neoaxis 編輯器的勁都沒有了。這一拖就拖到了現在。想來這位朋友應該早已解決Neoaxis的中文顯示問題了吧,再寫教程恐意義不大。Unity 的中文顯示機制和 Neoaxis 頗多類似,今天寫這篇文章也算是向那位朋友聊表歉意了。

還要說明的是,筆者才剛開始學習 Unity,講解中有錯誤或不准確之處還望指正,在此先行謝過。
  1. 流程說明 Unity 的 Asset 自動導入機制使得在 Unity 中顯示中文非常簡單。你所要做的就是將中文字體放到 Unity 的 Asset 目錄下,Unity 會自動將字體中的所有文字轉換成一張字體貼圖,並生成一個 Unity 字體。之後你可以就通過 GUI Skin\GUI Style 引用這個字體來顯示中文。要在 Neoaxis 中顯示中文的話,生成字體貼圖(或稱Bitmap Font)的過程不是自動的,你需要先用 Bitmap font generator 來生成字體貼圖及字體定義,然後通過 Neoaxis 自帶的字體轉換工具將字體定義轉換成 Neoaxis 的字體定義。對比這兩個引擎的字體導入流程,不難發現兩者的設計思路差異。Unity 的方式簡單高效但可控性差,Neoaxis 的方式略顯繁瑣,但你可以精確控制每一個步驟。
  2. 準備工作讓我們先打開任意一個 Unity 項目,這裡我們用的是 Unity 官方教程中的3D平台遊戲項目。Unity 的 GUI 採用的是 Immediate Mode GUI (IM GUI),對於更習慣Windows GUI 編程的朋友來說如果第一次接觸可能有點不習慣。簡單說來在 Unity 中創建 GUI 不需要進行通常的 Init(初始化)、CleanUp (清理)步驟,也不需要進行事件的發送、訂閱、處理,相反你只需在每幀的更新周期裡同時繪製 GUI 及處理相應事件就可以了。如果想更多了解 IM GUI 的話,不妨看看 mollyrocket.com 的這段視頻。mollyrocket 的論壇裡也有不少 IM GUI 的相關討論。在菜單中,選擇 GameObject->Create Empty, 創建一個空的 GameObject, 改個合適的名字,如 "MyGUIObject"。MyGUIObject將充當GUI的容器,具​​體界面的創建及位置都將通過腳本來進行。所以我們可以不關心這個 GameObject 在場景中的位置。這時層級視圖(Hierarchy)如下:

  3. 創建 GUI Skin 或 GUI StyleUnity 中的界面風格是通過 GUI Style 及 GUI Skin 來進行控制。GUI Skin 由一組 GUI Style 組成。GUI Skin和GUI Style的關係類似於 CSS 中CSS 文件和 CSS Style 之間的關係。本教程的重點不在於 Unity GUI 的講解,相關概念大家可以多參看 Unity Manual。在項目視圖(Project)中選擇 Create->GUI Skin 創建一個 GUI Skin,改名為 "ChineseFontSkin"。這時項目視圖如下:


    在屬性視圖(Inspector)中對 ChineseFontSkin 簡單設置如下:



    這時我們還沒有中文字體,字體一項就先用項目中帶的Fluoride字體,然後將 Button 中 Normal 的 Text Color 改成黃色。
    Button 是這個 GUI Skin 中關於按鈕的默認Style。


    然後,我們將 Label 中 Normal 的 Text Color 改成綠色。
    本教程只用到 Button 和Label。
  4. 通過腳本創建 GUI 在 Unity 中你可以通過 GameObject 菜單創建 GUI Text 和 GUI Texture 這兩個基本的 GUI 對象。但大部分 GUI 都需要通過腳本創建。我們將用腳本創建一個 Label 和一個 Button。在項目視圖(Project)中選擇 Scripts 下的 GUI 目錄,在本視圖的菜單中旋轉 Create->C Sharp Script,創建一個 C Sharp 腳本,改名為“MyGUI”。

    雙擊 MyGUI 腳本可以在 Unity 自帶的 UniSciTE 編輯器中打開腳本進行編輯。
    但由UniSciTE 無法正確顯示中文字符,使用外部 IDE 來編輯帶中文的腳本是個好主意。微軟的 Visual C# Express 當然是免費編輯器中的首選,但對於我們這個簡單的腳本來說,Notepad 就足夠了。
    在 Unity 項目視圖中右鍵點擊 "MyGUI",在彈出菜單中選擇“Show in Explorer”,可以看到我們的腳本文件。



    用 Notepad 打開 MyGUI.cs,輸入以下腳本:



    這個腳本做的事很簡單。
    先定義一個可設置的 GUISkin 對象 mySkin。在 OnGUI 方法中將 GUI 的 Skin 設為 mySkin,然後創建一個 Label 和一個 Button。Label 中顯示的中文拷貝自我們站點的 About 頁(上面截圖中文字未顯示完整)。保存腳本,用默認的 Ascii 編碼保存即可。回到Unity,將 MyGUI 腳本拖放到 MyGUIObject 上。選擇MyGUIObject,在 Inspector 中將 My Skin 設為 "ChineseFontSkin"。


    運行遊戲,可以看到英文文字能顯示,但中文都丟了。
    這是因為我們還沒有導入中文字體的緣故。

  5. 導入中文字體在 Windows 的 Font 目錄下,選擇你喜歡的中文字體(這裡我們選擇微軟雅黑),拷貝至 Unity 項目下的 Assets\GUI 目錄下。切換至 Unity,發現 Unity呈凍結狀,此時 Unity 正在進行字體貼圖及字體定義的自動生成工作。根據機器性能及字體大小,導入過程可能較長。(我的機器上需要10多分鐘。)
    等 Unity 完成工作後,可以看到 Project 視圖下的 GUI 目錄中多了個 msyh 的字體。
    (或其他你選擇的字體的名稱)在 Project 視圖中選擇 ChineseFontSkin,在Inspector 視圖中,將 Font 改為剛導入的字體 msyh。再運行遊戲。中文都可以顯示了。你好,Unity!

  6. Unity 乾了什麼及沒幹什麼?在Unity 中顯示中文是不是很簡單呢?再讓我們看看 Unity在背後乾了些什麼。在 Project 視圖中選擇 msyh 字體並展開,可以看到 Unity 為每個字體生成了一個字體貼圖(font texture)及一個字體材質(font material)。選擇font texutre,在 Inspector 視圖可以看到該貼圖的預覽:


    一張16M的4096x4096貼圖!
Unity 自動替你將微軟雅黑中所有可用文字都導成了一張巨大的位圖,而不管你是否真的需要這麼多文字。好處在於,現在你可以在 Unity 裡顯示所有微軟雅黑字體所支持的文字了。但是,為每個字體分配一張 16M 貼圖的做法太過奢侈了,對配置較低的機器或是 iPhone 來說更是不可接受。可是在 Unity 真正支持 TTF 字體渲染之前,我們似乎也只好接受這種傻瓜式生成字體貼圖的方式。

但我們對此真的無能為力了嗎?當然不!既然我們無法控制 Unity 生成字體貼圖的方式及過程(雖然通過 Editor API 的 TrueTypeFontImporter 類可以進行有限的控制),至少我們可以對字體本身做些改造,讓它只包含我們所需要的文字。就我們這個簡單的項目而言,我們希望看到的字體貼圖更應該是下面這樣的:



64K vs 16M。
除非你要開發 RPG 或是需要用戶輸入任意中文,改造字體的成效將非常可觀的。

在下一篇教學中我們將介紹如何利用 FontForge 來完成中文字體的瘦身工作。

[小編碎碎念:]
這篇文章出自大陸高手“死貓”之手,小編第一次在 UNITY 顯示中文就是參考這篇文章實做的。這幾天不約而同地被朋友以及 UnityIN 的看官們問了顯示中文這件事,想說把這邊文章轉載過來好了。

但目前聯絡不上“死貓”本人,所以若看官們有認識他或者“死貓”有看到這偏文章的轉載,對於文章版權上有所疑慮,請趕緊與我們聯絡,我們會以最快有誠意的方式取得你的同意,謝謝。


如果你覺得這篇文章對你有所幫助,請給我們一個“贊”吧!


UnityIN 總編輯:Bric Lin,
Email: ericlin09@gmail.com
曾任職台灣某遊戲公司研發Game Engine,為書籍“OGRE入門指南”譯者,專攻Rendering技術與遊戲開發,目前為獨立團隊CocosPlay主程式

1 則留言: