日本語化MOD用の Unity の asset の自動生成について

最近はテレワークの影響で仕事中の息抜き(散歩)ができず、かえって不健康になっている zan-gyo です。

 

Unity ベースのとあるゲームの日本語化を行っているのですが、現在進行形で新機能が実装されているゲームであるため 日本語化MOD に必要な .unity3d ファイルの頻繁な再生成が必要になっています。

翻訳自体は自宅サーバ上にある Zanata*1 という翻訳プラットフォームで行っているのですが、ゲーム内で翻訳内容を動作確認するには .unity3d の形式のファイルにパックしないといけません。

※ 私が関わっているゲームでは翻訳者向けにローカライズデータのみを差し替えられる仕組みが予め用意されていたので翻訳差分のみを .unity3d 化しています。

今回(?)はどうやれば .unity3d 形式でパックすることを自動化できるかの話です。

 

必要なもの:

- Unity 3D (エディタの機能のみを使うのでライセンスチェックは緩い模様?)

- パックするデータのフォルダ構造とメタデータ

- Tabletop-Simulator-Modding の TTSAssetBundlesMenuItems.cs ファイル。

github.com

 

↑の Tabletop-Simulator-Modding のファイル一式の中に Unity プロジェクトの Assets/Editor に展開する .cs ファイルがあるのですが、TTSAssetBundlesMenuItems.cs を所定の場所に設置すると Unity の Assets メニューに "Build AssetBundles" という項目が追加されます。

このメニュー項目を実行すると、.cs内のスクリプトによって Assets フォルダの中で出力対象に設定されているものがビルドされて、単体の .unity3d ファイルになります。

 

Build AssetBundles の自動化について

ビルド処理を自動化するにはコマンドラインから Unity 3D を起動して、メニュー項目を実行し、その後でプログラムを終了させる必要があります。

Jenkins (フリーのビルド管理ツール) に Invoke Unity3d Editor を追加している場合は以下のパラメタで実行可能です (Ubuntuで動作確認済み)。

-projectPath $WORKSPACE -batchmode -quit -nographics -executeMethod TTSAssetBundlesMenuItems.BuildAssetBundles
-projectPath $WORKSPACE

Jenkins が自動生成するビルド処理用の一時フォルダをプロジェクトファイルの所在地として指定

-batchmode 自動処理モードを指定
-quit 処理完了後にUnity3Dを自動終了
-nographics GUI を表示しない。
-executeMethod TTSAssetBundlesMenuItems.BuildAssetBundles メニュー項目を実行する

 

あとは:

  1. Unity3d が必要とするファイル一式を適当なソース管理システム (SVN / git) 等に登録して、Jenkins によって展開させる。
  2. 翻訳データを取得し、Assets フォルダ以下に展開する。
  3. 翻訳データの入っている親フォルダのメタデータで assetBundleName: を指定し、出力対象にする。
  4. Unity 3d で Assets のパッケージ化
  5. 生成されたファイルを配布用の場所へ移動

という流れになります。

#1 の Unity 3Dが必要とするファイル一式は使用する Unity3d のバージョンが上がったときだけに更新することになります(Unity 3dによってプロジェクトが自動アップグレードされますが、時間がかかるために予め外部で更新済みのプロジェクトを登録しておきます)。

 

 

 

*1:POEditのウェブ版のようなもので自前で設置する。 Javaベースで Docker Container を使うと展開が簡単だが MySQLバージョン依存のSQL文を使用しているためデータベースを最新にすると動かないことが多い。翻訳前データの取り込みに時間制限があるため1ファイルのデータ量が多い場合はシングルコア性能重視でCPUを選ばないといけない場合もある。1ファイル数万件の場合はAWS EC2ではスペックが足りない。

FuzeDrive SSD インストールメモ

FuzeDrive というのは Enmotus 社が出している階層化ストレージソフト。

ハードディスクとSSDをペアリングして高速化することができる。

キャッシュと違って階層化ストレージなので全容量が合算で使用できる。

もともとは Ryzen シリーズ用の StoreMI としてリリースされていたが、現在は単体で販売されている。尚、Ryzen用無料版 (SSD 128GBまで) は AMD のサイトでは配信停止されているが、Ryzen 用コストダウン版 が用意されている (FuzeDrive SSD にはハードウェアをライセンスとして認識する専用版がある)。

ww.enmotus.com

FuzeDrive SSD は Enmotus 社が出した階層化ストレージ構築用の SSD で、128GB SLC + 1.5TB QLC のハイブリッドとなっている。

実は QLC も TLCMLC も SLC もSSDとしての素子の数は同じで、違うのは保存できる電位の種別。

  1. SLC は 0 かそれ以外、
  2. MLCは 0 か 3状態
  3. TLC は 0 か 7状態
  4. QLC は 0 か 15状態

MLCTLCもQLCも安定して電位が保存できなくなったら素子としては死亡状態になるわけだけど、SLCに転用すれば延命できたりする。FuzeDrive SSDの場合は 元の容量が 2TB のQLC SSDで、512GB分のQLC素子をSLC運用することによって容量は4分の一に下がる (128 GB) が大幅なレスポンスの高速化と延命を可能にしている。

FuzeDrive SSDの有効化の手順だが、これは意外と落とし穴が多かった。

通常の手順は:

  1. インストール後に Windows Update 経由で Enmotus SSD ドライバを入れる。
  2. すると自動的に Microsoft Store からモニタリングツールが入り、SSD + QLC モードを初期化できる。
  3. 最後に Enmotus Fuzion X ツールをダウンロードして階層化ストレージを構成する。

ただし、 いくら Windows Update をしても最新版の Windows では Enmotus SSD ドライバが落ちてこないのである。

 

  1. Enmotus の SSD ドライバは以下から入手できる。

    www.enmotus.com

  2. Enmotus Fuzion モニタリングツールは以下から入手できる。

    www.microsoft.com

  3. Fuzion Xは以下から入手できる。

    www.enmotus.com

 

尚、 Enmotus SSD を使用する場合は FuzeRam メモリキャッシュは推奨されていないため Fuzion X には機能が含まれていない。 有料版の Fuzion XL を使用すれば FuzeRam も重ねることはできる。

 

 

MySQL で簡易 dhash 検索

dHash という画像検索用のアルゴリズムがある。

画像をグレースケール化して 9x8 のサイズにリサンプルし、隣合わせのピクセル同士を比較して増減に応じて 0 か 1 の値を設定して画像を 64bit 値にするというものだ。画像の検索には Binary Search Tree (2分探索木) を使って、3 bit 程度の誤差なら許容するような形で検索する。
※ グレースケール化やリサンプルのアルゴリズム、増減に応じて 0/1付与の方式によって dHash値の互換性が無くなるので長期の利用の際には互換性の維持については要注意である。

ただし Binary Search Tree を構築するのには時間と手間がかかるし、頻繁に検索するには Binary Search Tree のデータをメモリ上に長期間保持する必要があるので運用が面倒である。
そこで MySQL で Binary Search Tree を用いずに単純検索をしてみるとした場合、どうなるかを確認してみた。

MySQL には BIT(n) 型というのがあって、最大 64bit までの値を格納できる。今回はSIGNED/UNSIGNED関係にまったく気を配りたくないのでdhash値はBIT型にした。
※尚、UPDATE images SET dhash_bits = UNHEX(dhash); 等で16進文字列からBITへの変換は容易にできる。

一言でまとめると、MySQL には BITの立っている数を数える BIT_COUNT() 関数があるので単純に dhash同士でBITWISE XORしたものの立ちBIT数を数えれば良いようだ。

SELECT HEX(dhash_bits), BIT_COUNT(dhash_bits ^ b'1111000111110000111000100100000001100100010011001101001011111001') AS SCORE
FROM images
WHERE dhash_bits IS NOT NULL
  AND BIT_COUNT(dhash_bits ^ b'1111000111110000111000100100000001100100010011001101001011111001') <= 3
ORDER BY BIT_COUNT(dhash_bits ^ b'1111000111110000111000100100000001100100010011001101001011111001') ASC

※ 当然だが Binary Search Treeでは無いので大容量検索の場合は効率が悪くなる。

UNRAIDを試してみた

Linus Tech Tips (https://www.youtube.com/user/LinusTechTips/) でも紹介されていた UNRAID を試してみた。 

unraid.net

 

UNRAIDはよくある FreeBSD 型のソフトウェアRAIDNASアプリアンスだが、従来のものとは異なる独自路線を貫いている。

一言で言うと、「一日のデータ処理量はHDD一個に収まるぐらいだが、総データ量はバックアップが億劫になるぐらい大量にあって、且つデータロスは最低限に抑えたい」というニッチなものだ。

製品はUSBメモリにファイルを展開する方式で、30日間の機能無制限体験版 (要インターネット接続)が付いてくる。トライアル期間後は要ライセンス購入。

UNRAIDは RAID3 や RAID4 のようなパリティドライブ固定式のソフトウェアRAID方式だが「データをストライプしない」という特徴がある。

RAIDにおいてパリティのデータは他のドライブ上の情報を XOR 演算する等で求められるが、パリティ計算だけについて考えれば各ドライブ内のファイルシステムはまったく関係が無いわけだ。

極端なことを言うと 4台HDD構成で HDD1 を NTFS、HDD2 を exFAT、HDD3 を ext4 にしてもパリティは問題なく計算ができ (実際にUNRAIDがサポートするのは xfs, btrfs, reiserfs)、HDDロスト時にも残存ドライブの情報を元に欠損したHDDの情報を逆算できる。

RAIDの場合はデータをストライプすることによってパフォーマンス向上を狙うが、パリティドライブ数+1のHDD欠損で全データをロストする。UNRAIDでは各データドライブは通常のファイルシステムのまま運用されるので、複数のHDDが欠損しても残存HDD上のデータは専用の復旧ソフトの必要もなしに復元できる。必要なのは対象ファイルシステムに対応したLinux の Live Boot メディアだけだ。

尚、従来のRAID5/6ではパフォーマンス高速化のために以下のような最適化がとられているが UNRAIDはこれらの最適化を悉く外してきている。

従来のRAID5の最適化:

  • データストライプによる複数HDDの同時利用によるパフォーマンス高速化
    → ただしデータロストの危険性あり
  • パリティドライブ非固定によるHDD消耗の均等化
    → ただしHDD複数台同時故障の危険性あり
  • 一斉書き込みによる書き込み操作の単純化

 UNRAIDでの状態:

  • データをストライプしないので複数HDD同時欠損でも完全データロストしない(ただし1デバイス分の帯域しか使えないので転送速度が遅い)
    → 全ドライブ同時書込みをしないのでHDDの回転モーター同調の問題が発生しにくく、NASグレードのHDDを必ずとも必要としない(私見
  • パリティドライブが固定なのでパリティドライブが消耗しやすく、故障の予測が立てやすい
  • パリティ書込み時に他のドライブの内容を読み取ってからパリティ計算するので処理に二手間かかって遅い

UNRAID の問題だが、RAIDのパフォーマンス最適化を悉く外してきているためとんでもなく書き込み処理が遅いこと(特にパリティ計算による2重レイテンシーが致命的)だ。

そこでUNRAIDのパフォーマンスに関わってくるのがキャッシュドライブという名のワークエリアだ。キャッシュドライブはxfs / btrfs (2台でRAID1をする場合は btrfsのみ)でフォーマットされた作業エリアで、通常UNRAIDはキャッシュドライブに変更分のデータを書き込み、夜間にまとめてUNRAIDアレイに反映するという方式をとる。言ってみれば ソフトウェアRAID1から自動バックアップできる高可読性ソフトウェアRAID5/6がセットになっているわけだ。

一日の作業量がキャッシュドライブの容量に収まるのであれば読み書きは極めて速い。10GBe 等にも対応しているので適切に構築されたUNRAIDサーバであれば動画編集にもまったく問題なく対応ができるレベルだ。

UNRAIDでは分散構造のファイル階層を採用しており、キャッシュドライブと各HDDの中を横断したファイル階層をもっている。もし HDD1 に /share/backup/file1.txt というファイルがあり、HDD2 に /share/backup/file2.txt というファイルがある場合、外から見ると一つのフォルダに双方のファイルがあるように見える。

各HDDにファイルが書き込まれる時にはネットワーク共有毎に設定できる三つの分散アルゴリズムのうちの一つが使用される。

  • High-Water: 水槽から溢れた水が隣の水槽に注ぎ込むイメージ。HDD1を50%まで使い、HDD2を50%まで使い、全部50%まで貯めたらHDD1を75%まで貯める、という方式
  • Most-Free: 空き領域が一番多いHDDに配置
  • Fill-up: HDD1から順番に配置し、一杯になったら次のHDDに移動

UNRAIDアレイ上のフォルダ構造の分割はファイルの書き込み毎に行われるが、一度ファイルの書き込みが始まると対象HDDは固定になる。最初に0バイトファイルを作成した後でファイルを拡張し、対象HDDの空き領域を超えるデータ書き込みを行うと「容量不足エラー」になるのだ。同じファイルを2度目に書き込むと別HDDに配置されるので問題回避できるが同様の問題はキャッシュドライブ側でも発生する(キャッシュドライブの容量を超過する書き込みは自動的にUNRAIDアレイに直書きになる)。サーバ間引っ越しでデータを大量に書き込んでキャッシュドライブ容量を超過すると一時的に容量不足エラーで爆死する(再実行で直る)。

※ キャッシュドライブの容量内で運用している場合はUNRAIDアレイに変更を反映する時点でファイルサイズが固定化しているためこの問題は発生しない。

 

尚、UNRAID は FreeBSD系のNASソフトウェアであり、当然のように同系統のSMBの制限によって制約される。ファイル名 255バイト制限だ。

UNRAID の対応ファイルシステムは xfs (最大ファイル名 255バイト)、btrfs (255バイト), reiserfs (4Kバイト) と長いファイル名に対応している reiserfs にも対応しているが、これは以前のバージョンとの下位互換性のために用意されているだけで reiserfs を使うことによってファイル名長の制限を回避することはできない(推奨は xfs)。

という感じで通常のNASユーザーには使いづらいことだらけだが、PBクラスのストレージ容量を扱って 且つRAID破損によるデータロストを避けたいのでれば十分に検討しても良いものだ。ライセンス価格は接続HDD数ごとに分かれているが、大量HDDでも価格は安い。

unraid.net

 

ネットワーク回りではUNRAID は FreeBSDと同様に マルチギガ (10GBe+) 等に対応しており、複数NICの場合は bonding モード (複数NICのロードバランス)とbridge モード (子ネットワークノードからの通信が親ノードに流れる)に対応しており、NASに接続した 10GBe 側から通常の Gigabit ネットワークに通信を流すような運用も可能だ (DHCPが通過するかは未確認)。

また、Dockerや仮想マシンの実行機能も備えており、夜間処理用にハイパフォーマンスCPUを備えても、処理能力は無駄にはならない(コミュニティアプリストアからパッケージの導入も可能)。

尚、筆者は低消費電力CPUのオンボードSATAで手軽にホームNAS、と考えて Athlon 3000G (2C4T、35W TDP) でシステム構築したがUNRAIDアレイ直書き時のスループットが 40MB/秒で最初のサーバ間コピーが長すぎて泣く泣く 2720A SGL を購入して Windows Server運用に切り替えた。

STRICT_TRANS_TABLES 回避

昔改造したウェブサイトを Ubuntu 12.04 LTS の環境から Amazon Linux (CentOS) に移植したところ、
一気に動作不良に。

エラーは 1366: Incorrect integer value: '' for column 'hoge' at row 1 というもの。

なにやら最近の MySQL/MariaDBでは では STRICT_TRANS_TABLES なる sql_mode が設定されていて型の自動調整が無効になっているらしい。

my.cnf で書き換えてみたところ

[ERROR] mysqld: Got error 'File size bigger than expected' when trying to use aria control file '/var/lib/mysql/aria_log_control'

というエラーが発生してMySQLが起動しない。 aria_log_control というファイルを削除しないといけないみたいだ。

結局、 init-file を my.cnf で定義して以下のSQL分をサーバ開始と同時に実行するようにした。

SET @@GLOBAL.SQL_MODE = REPLACE(@@GLOBAL.SQL_MODE, 'STRICT_TRANS_TABLES,', '');

もっと良い方法が無いものかな。

Keian KEM-89B に 別OSを入れる作業メモ

  • Keian KEM-89Bはそこそこ良い低価格タブレットPC
    http://www.keian.co.jp/products/products_info/kem_89b/kem_89b.html
  • Intel Z3735F 4C/4T でメモリは 2GB、ストレージは 32GB
  • インタフェースは USB 2.0、MicroUSB (充電専用)、MicroHDMI、イヤホン、MicroSD
  • 画面サイズは 1920x1200 IPS 広視野角液晶 で 8.9インチサイズ
  • OS は Windows 8.1 with bing
  • 困ったことに初期状態で ComponentStore が破損しているので機能の追加や上位版へのアップグレードが行えない上に再構築に必要なファイルが廉価版なので削られている、どん詰まり状態。
  • Windows Update はできる。

※追記 2015/6/24 - Keianの製品ページにて修正版OSデータの配布受付をしている様子です。

そこでOSを再インストールしてWindows 8.1 Pro x86 にしようかと (Baytrail 世代は 32bit UEFI のため x64 はインストールできない)。

※※※ 超重要:先に 回復メディアを作っておきましょう ※※※

  • OSを再インストールすると当然のようにドライバが一切ない状態になるので事前にドライバを集めておく。

OSのインストール後:
1. Z3700 series platform driver を入れてから再起動。
2. デバイス一覧から不明なデバイスを一つ一つ開いて 環境特有ドライバのフォルダを検索させて登録する。
3. Sensors 以下に隠れた 不明なデバイスがあるので Kionix の kxfusion ドライバを適用して再起動。
4. レジストリに以下の値を追加する。
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\ROOT\SENSOR\0000\Device Parameters\kxfusion]
"Orientation"=hex:01,01,00,00,01,01,02
再起動すると画面の回転が自動で行われるようになる。
5. 保存しておいた TouchSettings.gt を \Windows\inf に戻して再起動するとタッチパネルが正しく動作するようになる。
6. 最後にネットワーク接続を設定した上で Intel Driver Update Utility を入れておくと GPU の最新ドライバを検出してくれる。

ここまでの必須ファイルはこちら。
https://www.dropbox.com/s/encr642fggq9g86/KEM-89B%20Drivers.rar?dl=0

rpmb対策

  • Venue 8 Pro の eMMC には Replay Protected Memory Block (rpmb) なる領域があって、これは専用コマンドで無いと読み書きができないため普通にアクセスしようとするとエラーが多発する。
  • エラーが一度発生すると 8 秒ほどI/Oがブロックするので操作性が著しく悪くなる。
  • カーネルパッチして除外すると正しく動作するらしい。

https://dev-nell.com/rpmb-emmc-errors-under-linux.html
https://bugs.launchpad.net/ubuntu/+source/udev/+bug/1333140

いまのところここまで。