ワンバイナリでローカライズ対応したゲームを開発した時の話

前置き

こんにちはヾ(@⌒ー⌒@)ノ

癒し系魔法エンジニアとして前回の記事担当の@mix3から紹介されました@p_chinです('Θ' )

普段はPOCKET FOOTBALLERというゲームの新機能開発などをやっておりますフロントエンジニアです。( 'Θ' )

ポケフト

今回はこちらの開発中に作成したローカライズのシステム周りの一部について書いていこうと思います( 'Θ')

本投稿はTech KAYAC Advent Calendar 2015の12/19の内容になります。

目次

開発の経緯

このポケフトというアプリは大前提として、初回リリース時から世界公開を目標にしていたプロジェクトでしたので、ワンバイナリで多言語表示に対応したゲームを作成する必要がありました。

まぁ他にも過去のつらい経験の反省を生かしてワンバイナリでローカライズ出来る様にした...という経緯も個人的にはありますので過去のローカライズ事例については、昨年のAdventCalenderで触れているので良かったらどうぞ。

ローカライズシステムの簡単な概要

初回起動時に標準言語を決定する処理フロー

標準言語はモバイル端末のOS設定から決めます。

  1. アプリ起動
  2. 対応言語リストをサーバーから取得
    • ここまでにユーザーへ伝える情報(エラーなど)は、とりあえず英語で表示
  3. 初回起動端末ならばOSの言語設定が対応言語リストに含まれてれば表示言語をそれに自動決定
    • OS設定の言語が未対応ならば、とりあえず英語を表示する

基本機能

  • 起動後→AssetBundle読み込みまでの翻訳はアプリに組み込まれてる
  • その他の翻訳はTextAssetとしてAssetBundleから配信されている
  • 翻訳テキストはkey&value形式で管理されていて、keyから現在の言語の文字列を取得する
    • (NGUIの標準のローカライズ機能を使用)

ローカライズ補助ツールについて

翻訳テキストの管理

ポケフトではNGUI3.0.6f7を使用していたので、言語毎に {language}.txt を用意して、それをNGUIのLocalizationコンポーネントに参照させて翻訳処理を行っていました。

過去にローカライズしたプロジェクトではエンジニアが温もり溢れる手動編集でja.txten.txtの翻訳を編集していたのですが、ポケフトは初回リリース時に対応する言語が当初は5ヶ国語あったので手動でエンジニアがメンテナンスするのは辛そうです。

なので、GoogleSpreadsheetで翻訳を管理して、そこから各言語の翻訳txtを出力するシステムを弊社技術基盤チームの@sumipanに作成していただいた感じです。

ちなみに現在は専用のgithubのissueからsetup {unity_project_repositry_branch_name}と入力するだけで翻訳の出力が完了するというよしなシステムになって稼働中です。

github-scriptというgemを使って可能にしてる様です。

Sceneにハードコードされたtextを検知するテスト

.unity.prefabなどのComponentの情報がシリアライズされてるファイルの中に文字列がハードコードされていた場合にはgithubのpull-requestのテストが失敗するという仕組みです。

NGUIのUIlabelというゲーム内のラベルを制御する為のComponentがあるのですが、そちらのmTextというシリアライズされたフィールドに何かしらの文字が入っていた場合にpull-requestのテストを失敗状態にします。

※ちなみにmTextとはUnity上では以下の様に表示されてる値のことです。

mTextのinspectorの表示

こちらの仕組みもissueを書いたら@sumipanに作って頂けたので技術基盤チームは素晴らしいと思いました。

この仕組みが必要になった経緯

Sceneのセットアップ処理の中でExceptionが起きてしまった場合に製品版のアプリにハードコードされた文字が不本意にユーザーに見えてしまう可能性があるのが危険だと思っていたのが理由です。

たとえば『うんこ』とハードコードされたままリリースしてしまい、Sceneのセットアップ時にこのtextを設定する前の処理で例外が発生して画面が見えてしまった場合には大問題ですよね。

また、多言語化を想定したゲームだったので、英語の言語設定してるユーザーがいきなり日本語を見てしまった時には不快になると思ったのも理由の一つです。

画面作成ルール

ゲーム画面のローカライズをするにあたって、開発を効率化する為にプロジェクト発足時に幾つかのルールを決めました。

デザイン上のルール

基本的に画像にラベリングする(ローカライズする必要のある文字を書く)のをデザイナーに避けてもらっていました。

理由

ラベリングすると、その画像の翻訳管理をしなければいけなくなるからです。

その為、デザイナーから強い要望が無い限りは、ゲーム内に埋め込まれてるフォントの文字列をゲーム内に表示する方針にして貰っていました。

過去のプロジェクトをローカライズした時に、ラベリングされた画像が多かったので翻訳のコストが高かった経験も生かしての判断でした。

テキストが描画範囲を超えた場合のルール

以下の画像の通りです。(デザイナーが画像でルールを定義してくださってたので抜粋してみました)

text-ruleのサムネール画像

画面に表示する文字列をmTextにハードコードしない

先ほどSceneにハードコードされたtextを検知するテストの項目で説明した通りです。

参考資料

Google開発者ガイドのローカライズのチェックリスト

文字列管理などの思想が個人的には結構良いと思っててローカライズシステムを設計する時の参考になります。

(僕はシステム作り切った後で見ましたが。。)

終わりに

さて、一部のみの紹介になってしまいましたが如何でしたでしょうか?

githubに挙げられるコードは用意出来なかったのですが、今後ゲームのローカライズする方のお役に立てれば幸いです。 :pray:

さて、明日は谷脇さん(@mackee_w)による『人体と電気』についてのエントリーになります!

楽しみですね[-o-]

#23 3Dドット絵をつくる -コンチをドット絵にして3D化したぞ!!-

こんばんは、@takashicompanyこと、タックルです。
普段はUnityでゲーム作ってます。
この記事は、tech.kayac.com Advent Calendar 2014 23日目となります。 がんばります。

100.png101.gif

ふと思い立って、弊社の象徴・マスコットキャラクターであるコンチ勝手に3Dドット絵にしたので、3Dドット絵を作るときのフローを紹介したいと思います。

ちなみに、出来合いのものはGitHubに一式あがっているので、もし欲しい方いたらどうぞ。

今回紹介する3Dドット絵作成フローはUnityのMecanimで人間のアニメーションそのまま適用できるようにしました。

下絵を描く

00.png

まずは、3Dモデルを制作する際の下絵から描いていきます。
下絵を描くツールは、特に指定はありません。なんでも良いです。
陰影や枠線などはつけず、全体象を捉えられるくらいでOKです。
できたら.png形式で保存しましょう。

3Dドット絵をつくる

01.png

今回はQubicle 2.0を使います。
Qubicle 2.0はフリーで利用可能(エクスポートなどはライセンスを購入する必要あり)です。
Windows/Mac版がリリースされており、Windowsのペイント感覚で3Dドット絵(ボクセルアート)を作ることができます。

201.gif

1. Qubicleに下絵をインポート

まずは、下絵をQubicleに取り込みます。 File > Import > PNG で選択できます。

取り込むとこんな感じで表示されるはず。
02.png

下絵で透過されていた部分が灰色になって表示されるので、魔法の杖ツールなどで選択して消してしまいましょう。
03.png

2. 下絵から3Dドット絵を削り出していく

下絵に奥(Z方向)に引き伸ばし、3Dモデルを削りだしていきたいと思います。
Tools > Extrude Tools を選択して、引き伸ばしを行います。
04.png

引き伸ばしができたら、後は鉛筆・消しゴムツールなどで、モデルを削って行きたいと思います。
04_a.png

完成したコンチはこんな感じ。
05.png

正面・側面・上面・斜めから見て自分のイメージとあっているかをチェックしながら微調整をするのがコツです。

3. 関節ごとに3Dドット絵を分割する

3Dドット絵モデルができたら、関節ごとに部品を分割します。

分割したいボクセルを選択して、Modify > Detatched > Sprit offで分割することができます。
今回、コンチはこんな感じで分割しました。
06.png
(画像は分割をわかりやすくするため各パーツを離して配置していますが、本来は元の位置のまま分割します)

分割の区分は下記になります。

  • 上腕(左右)
  • 下腕(左右)
  • 上脚(左右)
  • 下脚(左右)

4. .obj形式でエクスポート

分割ができたら、.obj形式でエクスポートしましょう。
(書き出しはQubicleのライセンスの購入が必要になります。)
書き出しの際の設定は↓になります。
07.png

  • <ファイル名>.mtl
  • <ファイル名>.obj
  • Materials/<ファイル名>_Atlas_tex.png

が書き出されれば成功です。

3Dドット絵モデルにボーンをつける

10.png
ここからは Blenderを使います。

1. Blenderにobjファイルをインポート

生成した .objファイルをBlenderに取り込みたいと思います。
File > Import > Wavefront (.obj) で.objファイルを選択してください。

3Dドット絵モデルがBlender上に表示されます。
11.png

ドットがボケて表示されてしまう場合は、レンダリング時には解消されるので、そのままで大丈夫です。

2. ボーンを作成する

3Dドット絵モデルにあったアーマチュア(ボーン)を作成します。
12.png

ボーンの階層構成はUnityのMecanimの仕様に沿ったものにします。 13.png

ここではボーンを作るところまででOKです!

3. 関節ごとにVertex Groupを作成する

頂点をグループ化(Vertex Group)して、 7.で作ったボーンとメッシュを適用する下準備をしたいと思います。
関節ごとに分割された状態でBlenderにメッシュがインポートされているかと思うので、それをそのままVertex Groupとして登録します。
14.png

全ての関節をVertex Group化します。

4. 各メッシュ(関節)を一つのオブジェクトにまとめる

全ての関節のVertex Group登録が終わったら、メッシュを一つのオブジェクトにまとめます。
15.png

メッシュオブジェクトを全て選択した状態でCtrl + Jを実行すると、メッシュがひとつのオブジェクトにまとまります。 16.png

17.png

5. ボーンとメッシュを結合する

続いて、ボーンとメッシュを結合します。
アーマチュアの子階層にメッシュを配置する感じとなります。

メッシュ → ボーン(アーマチュア)の順で選択してCtrl + P > Armature Deform > With Empty Groupsを実行します。
18.png

6. ボーンと関節のVertex Groupを連携させる

メッシュを選択した状態でEditModeに切り替えると、Vertex Groupsの項目に各ボーン名と同じVertexGroupが空の状態で定義されています。
このVertex Groupに頂点を登録すると、ボーンを動かした際に登録した頂点(メッシュ)が動きます。
3.で設定したVertex Groupをそれぞれのボーンに設定(Assign)します。
19.png

今回の3Dドット絵では、ドットの粒感を出すために、自動のウェイトペイントではなく、手動で頂点ごとに設定する方式を採用しました。
自動ウェイトペイントを使うと、また違った動きをする3Dドット絵ができあがるので、試してみても良いかもしれません。

7. 関節が正しく動いているかを確認する

PoseModeでボーンを動して、確認をしましょう。
20.png

Unityに3Dドット絵モデルをインポートする

細かい手順についてはこちらをご覧ください。

注意点としては

  • 3DモデルをBlenderから.fbx形式でエクスポートした後に、Unityにインポートする際に、.obj生成時に作られたpngファイルもインポートし、マテリアルに設定する
    • .fbxをインポートしただけだと、マテリアルにテクスチャーが設定されない
  • マテリアルのテクスチャのテクスチャー設定でFilter ModeをPointに設定する
    • 設定しないとドットがぼやけて表示されることがある

を忘れずに!

ボーンの構造がUnityのMecanimの仕様に合わせているので、人間用に作られたアニメーションを適用することができます。
102.gif
腕が短いため、剣の両手持ちとかはできないですが…(-_-;)

ちなみに、3Dドット絵コンチの頂点数は1088なので、ダイナミックバッチングの適用外ですが、比較的軽い3Dモデルではないでしょうか。
103.png

明日はゆるふわぽわわ系エンジニア、acidlemon氏がフィナーレを飾ります!
これは期待ですね!!!!