(忘れる程時間が経っていると各種ツールのバージョンが上がっていて、これまでのやり方が通じなくなっていた…なんて事は良くあるので無駄になるかも知れませんが…)
1. Unityの判断(Unity以外, x86/x64, Mono/IL2CPP)
XUnity.AutoTranslatorはUnityというゲームエンジンが使用されているゲームでなれば利用することが出来ません。このUnityには種類があり、ゲームが使用しているUnityの種類に合わせたBepInEx(後述)をインストールする必要があるためUnityの種類をまずは判断する必要があります。種類 | 判断方法(条件) |
---|---|
Mono x86 | game_Data というフォルダがある game_Data\Managed というフォルダがある game.exe が32bitである |
Mono x64 | game_Data というフォルダがある game_Data\Managed というフォルダがある game.exe が64bitである |
IL2CPP x86 | game_Data というフォルダがある game_Data\il2cpp_data というフォルダがある game.exe が32bitである ※私はこの種類のゲームを見たことがありません |
IL2CPP x64 | game_Data というフォルダがある game_Data\il2cpp_data というフォルダがある game.exe が64bitである |
Unity以外 | 上記以外 |
TheRoom4であれば"OldSins.exe"という実行ファイル名で"OldSins_Data"というフォルダが存在します。
2. BepInExのインストール
BepInExはMOD(プラグイン)に共通して必要となる様々な機能を提供してくれるMODで、このようなプログラムは『前提MOD』と呼ばれることがあります。またBepInExが提供してくれる機能で特に重要なのが外部コード(プラグイン)をゲーム内部で動作させる(ロードする)機能で、この機能を持つプログラムは『ローダー』と呼ばれることがあります。
XUnity.AutoTranslatorは様々なローダーに対応しているようですが、BepInExが推奨とありますのでそれに従いBepInExをインストールします。 インストールするファイルはUnityの種類によって変わってきます。2023年6月時点での最新版は下記のとおりです。
使用するファイルは特別な理由のない限り最新のリリース版で良いと思います。ただIL2CPPはBepInEx6からのサポートで、BepInEx6のリリース版が現時点ではありません。
そのためIL2CPPはプレリリース版を使用します。(プレリリース版よりも新しいbe版もありますが現時点でXUnity.AutoTranslatorは最新be版に対応していません。pre版と最新be版はnamespaceがBepInEx.IL2CPPとBepInEx.Unity.IL2CPPで異なっていることもありプラグインが未対応だと動作しません。)
種類 | ファイル |
---|---|
Mono x86 | BepInEx_x86_5.4.21.0.zip |
Mono x64 | BepInEx_x64_5.4.21.0.zip |
IL2CPP x86 | BepInEx_UnityIL2CPP_x86_6.0.0-pre.1.zip |
IL2CPP x64 | BepInEx_UnityIL2CPP_x64_6.0.0-pre.1.zip |
その後エクスプローラー等で"BepInEx\LogOutput.log"(ログファイル)が作成されているかを確認します。
作成されていればメモ帳等で開き重要そうなエラーがないかを確認します。
特に重要そうなエラーがなければBepInExのインストールは完了です。
BepInExのトラブルシューティングに沿って解決を試みます。
(実際にTheRoom2では真っ暗な画面で先に進まなくなりました。こちらに記載されているとおり"BepInEx/config/BepInEx.cfg"の[Preloader.Entrypoint]のTypeをMonoBehaviourへ変更したら解決しました。)
またUnityの種類(x86/x64, Mono/IL2CPP)とインストールしたzipファイルもあっているか再度確認してください。
間違いが見つからない場合トラブルシューティングに有益な情報がないか探してみてください。
また残っているエラーメッセージで検索し解決策がないかを調べます。
3. XUnity.AutoTranslatorのインストール
続いてインターネットの翻訳サービスを用いてゲーム内テキストの翻訳をしてくれるMOD、XUnity.AutoTranslatorをインストールします。 インストールするファイルはBepInEx版で例によってUnityの種類によって変わってきます(しかしx86とx64は区別なし)。2023年6月時点での最新版は下記のとおりです。こちらもインストールするのは基本的に最新リリース版で良いと思います。
種類 | ファイル |
---|---|
Mono x86 Mono x64 |
XUnity.AutoTranslator-BepInEx-5.2.0.zip |
IL2CPP x86 IL2CPP x64 |
XUnity.AutoTranslator-BepInEx-IL2CPP-5.2.0.zip |
その後エクスプローラー等で"BepInEx\LogOutput.log"(ログファイル)を開き"[Info :XUnity.AutoTranslator]"から始まる行があればXUnity.AutoTranslatorのインストールは完了です。
(翻訳サービスに接続できないだけでもエラーになるのでXUnity.AutoTranslatorのエラーはここでは無視します)
4. XUnity.AutoTranslatorの基本設定および効果確認
下表のとおり設定ファイルを書き換えます。設定ファイル:BepInEx\config\AutoTranslatorConfig.ini | |
項目 | 変更理由等 |
---|---|
[Service] Endpoint=DeepLTranslate |
翻訳サービスを指定します。GoogleTranslateV2がデフォルトになっていますが私の環境ではかなり高確率で失敗するのでDeepLTranslateにしています。ここはご自身の環境や好みで読み替えてください。 |
[General] Language=ja FromLanguage=en |
翻訳先・翻訳元の言語指定です。デフォルトでは日本語→英語になっているので英語→日本語へ変更します。 |
また[Alt]+[T]で原文⇔訳文を切り替えることができるので、英語がアヤしい時などは利用してみてください。
なお、ゲーム中の操作がしづらい場合は[Alt]+[T]で原文に戻して操作してください。
①XUnity.AutoTranslatorがテキスト(文字)を取得できていない
"Translator"を変更し再度テキストを読み込む為にゲーム中の操作で少し画面を切り替えて(メインメニューからオプションメニューへ行った後にメインメニューに戻るなど)ください。
下図のように"Served translations"が増えれば、そのTranslatorが使用できています。ゲーム画面に何らかの変化(日本語表示された/文字が消えた)が起きているはずなので前述に従ってください。 変更後のTranslatorでも"Translator status"がShutdownになる場合は また別のTranslatorを試したり、そもそもインターネットに接続できるかなどWindowsの設定を見直してみてください。
単に今まで表示された画面にテキストがなかった(表示された英語は文字情報ではなく画像だった)だけかも知れないので、オプションメニューへ変えてみたりゲーム本編の画面まで進めて見たりして、ゲーム中で様々な画面を表示させてみます。
それでも"translations"が4つとも0で変わらない場合はゲーム内の操作でゲームを終了しログを確認します。
もし何らかのエラーが残っていた場合はそのエラーによってテキスト取得が失敗しているのかも知れないのでエラー内容を調査します。
また設定ファイル内の[TextFrameworks]の全項目をTrueにして変化があるか?などを試してみます。
5. XUnity.AutoTranslatorで日本語表示されないときの対応
XUnity.AutoTranslatorの翻訳結果が表示されない(文字が消える/□が表示される)のはゲーム内のフォントが日本語表示に対応していないために発生しています。これはゲーム内のフォントを日本語表示可能なフォントへ変更すれば解消することができます。
①XUnity.AutoTranslatorの機能を利用(TextMeshPro または UGUI のみ)
②XUnity.AutoTranslatorを改造して無理やり日本語表示(NGUI のみ)
③ゲームを改造(リソースの変更など)
またドキュメントによればテキストフレームワークが UGUI の場合でも設定ファイルを変更すればフォントを変更できるようです。しかし、こちらは使用したことがないので本記事では扱いません。(設定ファイルの"OverrideFont="で指定可能。コードを流し見る限りWindowsにインストール済のフォント名を指定するようです。)
③は いわゆる日本語化MODで、ゲームを解析してリソース(場合によってはコードも)を変更し日本語表示可能なフォントにする方法です。ゲーム毎の解析が必要なので本記事では扱いません。
②はTheRoom2,3で行った方法で①と③の中間です。TheRoom2を日本語表示させようとdnSpyで適当にイジっていたらNGUIでの日本語表示可能なフォントの簡単な作成方法がわかったのでXUnity.AutoTranslatorを改造して実装した…という方法です。
5-1. テキストフレームワークの判定
下表のとおり設定ファイルを書き換えます。設定ファイル:BepInEx\config\AutoTranslatorConfig.ini | |
項目 | 変更理由等 |
---|---|
[Behaviour] EnableTextPathLogging=True |
XUnity.AutoTranslatorがテキストを設定する際、その設定対象の情報をログに出力します。ログ出力の頻度が高めなので、ひと通り調査が終わったらFalseに戻すことをおすすめします。 |
[Info :XUnity.AutoTranslator] Setting text on 'TMPro.TextMeshProUGUI' to '現在のプロファイル'
[Info :XUnity.AutoTranslator] Path : /UI Root Canvas (2D)/RootPanel/SelectGamePanel/CurrentProfile/Current Profile Text
[Info :XUnity.AutoTranslator] Level: 1
[Info :XUnity.AutoTranslator] Setting text on 'UILabel' to '現在のプロファイル'
[Info :XUnity.AutoTranslator] Path : /UI Root (2D)/Camera/Anchor/SelectGamePanel/Anchor Top Right/Current Profile Label
[Info :XUnity.AutoTranslator] Level: -1
クラス名 | テキストフレームワーク |
---|---|
UILabel | NGUI |
TMPro.TextMeshProUGUI | TextMeshPro |
この後はテキストフレームワーク毎の対応となります。なおTextMeshPro、NGUI以外はわからないので本記事では扱えません。(UGUIは前述の通り"OverrideFont="で何とかなるかも??)
5-2. TextMeshPro時の対応
TextMeshProの場合はXUnity.AutoTranslatorの機能で外部ファイルのフォントへ変更することが可能です。この機能はゲームのリソース(Assets)を後からロードするAssetBundleというUnityの仕組みで作られています。そのため、ゲームと外部ファイルのバージョン(UnityとTextMeshProの両方 特にTextMeshProが重要?)が一致していないと正しく読み込めない場合があります。圧縮ファイル | ファイル | 用途 |
---|---|---|
TMP_Font_AssetBundles.zip | arialuni_sdf_u2018 | Unity 2018用 |
arialuni_sdf_u2019 | Unity 2019用 |
次にどちらのファイルを使用するかUnityのバージョンを確認するためログを開きます。ログには下記のような行があり、この場合(TheRoom4)は 2019.4.5f1 であることがわかります。
[Info :XUnity.AutoTranslator] Loaded XUnity.AutoTranslator into Unity [2019.4.5f1] game.
設定ファイル:BepInEx\config\AutoTranslatorConfig.ini | |
項目 | 変更理由等 |
---|---|
[Behaviour] OverrideFontTextMeshPro=arialuni_sdf_u2019 FallbackFontTextMeshPro= |
テキスト更新時にフォントを指定されたもので上書きします。FallbackFontTextMeshProの利用が推奨されていますがファイルが利用できるか確認するため必ず上書きされるOverrideFontTextMeshProを使用します。なおFallbackFontTextMeshProは空欄にしてください。両方指定されているとAssetBundleの二重ロードで失敗した場合にFallbackFontTextMeshProのみ指定された時と同様の動きとなるためです。 |
しかし今はOverrideFontTextMeshProに設定しているのでFallbackFontTextMeshProにだけ指定した場合はどうなるか試してみてください。
特にOverrideFontTextMeshProにだけ指定した時と変化がないようならFallbackFontTextMeshProにだけ指定した状態で使用してください。(FallbackFontTextMeshProの利用が推奨されているため)
文字が消えたり□に戻ってしまう場合はOverrideFontTextMeshProにだけ指定した状態で使用してください。
[Info :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from internal Resources API.
[Info :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from asset bundle.
[Error :XUnity.AutoTranslator] Could not find the TextMeshPro font asset: arialuni_sdf_u2019
この場合は自分でファイルを作成すれば日本語表示が可能になるかも知れません。他にもっと良い方法があるかも知れませんが、私はUABEAでゲーム内のフォントを開きデータ構造からバージョンを判断しました。
UABEAでarialuni_sdf_u2019を開きます。圧縮されているので展開先を聞かれます。[Memory]を選択します。
その後[Info]をクリックします。開いたAsset Infoウィンドウで"ARIALUNI SDF"(Type=MonoBehaviour)を選択し[View Data]をクリックします。
この時に表示されるデータ構造がどのバージョンのTMPro.TMP_FontAssetであれば辻褄が合うかを調べます。
・v1.3以前にはTMP_FontAsset.versionが存在しない。
(Fieldsにも基底クラスのTMP_Assetにも見つからない)
・v3.2までversionは"1.1.0"のまま変化なし。
・v4.0からTMPro.TMP_FontAssetは非推奨??
UnityEngine.TextCore.Text.FontAssetが使用される?
・v1.2以前にはTMP_FontAsset.creationSettingsが存在しない。
(かわりにTMP_FontAsset.fontCreationSettingsが存在する)
条件にあうデータが複数ある場合はどれでも大丈夫です(データ構造は同じはずです)。そのため、UABEAで開くファイルは"game_Data\resources.assets"で大丈夫だと思いますが、もし見つからない場合は"game_Data\sharedassets0.assets"等のファイルも探してみてください。
UABEAで"OldSins_Data\resources.assets"を開きます。Asset Infoウィンドウのメニューバーから[View]-[Filter]でType Filterウィンドウを表示。[Deselect all]で全非選択にした後[MonoBehaviour]のみをチェックして[X]で閉じる。いちばん初めのデータが"Anton SDF"と" SDF"で終わっているので[View Data]をクリック。表示されたデータの先頭行が"MonoBehaviour Base (TMP_FontAsset)"となっているのでこのデータの構造を見ていきます。
・v1.0.26 : AscII_Leftなし
・v1.0.26 : なし (FormerlySerializedAsの記載あり)
・v1.0.25 : なし (FormerlySerializedAsの記載あり)
・v1.0.23 : あり
・v1.0.21 : あり
データ構造 | TextMeshPro |
---|---|
m_Versionがあり"1.1.0"である | v1.4~v3.2 |
m_CreationSettingsがありm_Versionがない | v1.3 |
fontCreationSettingsがありm_CreationSettingsがない | ~v1.2 |
m_kerningPair内にAscII_Leftという項目がある | ~v1.0.23 |
arialuni_sdf_u2019と同じようにファイルを配置・設定ファイルの変更を行い日本語表示できるか確認します。
種類 | フォルダ |
---|---|
Mono x86 Mono x64 |
game_Data\Managed |
IL2CPP x86 IL2CPP x64 |
BepInEx\unhollowed |
何というファイル名へ書き換えればよいのか確認するため、ゲーム内のAssetsから"TMP_FontAsset"(Type=MonoScript)を探します。TheRoom4では"OldSins_Data\globalgamemanagers.assets"にありましたが必ずどのゲームもこのファイルにあるとは限らないと思います。なかなか見つからない場合はAssetStudioなどフォルダごと読み込める別ツールを使用して探してください。
UABEAでAssetBundleを開き"TMP_FontAsset"(Type=MonoScript)を表示する一歩手前まで進み[View Data]ではなく[Edit Data]をクリックします。表示されたEdit Dataウィンドウでm_AssemblyNameを書き換えて[OK]をクリック。Assets Infoウィンドウのメニューから[File]-[Save as...]を選択するともう一つのウィンドウでもセーブするようにメッセージが表示されるので[OK]。Assets Infoウィンドウを閉じて、タイトルが"UABEA"となっているウィンドウでもメニューから[File]-[Save as...]を選択する。新しいファイル名をつけて[OK]をクリックしUABEAを閉じます。この新しいファイルのままでも使用できますが、無圧縮になったため変更前に比べてファイルサイズがかなり大きくなっています。そのためUABEAで圧縮します。UABEAで新しいファイルを開きメニューから[File]-[Compress]を選択。再度新しいファイル名をつけて[OK]をクリックします(この時上書きは不可みたいです)。圧縮方式を聞かれるので[LZMA]をクリック。圧縮が完了したらUABEAを閉じます。必要に応じて圧縮前のファイルを削除したり圧縮後のファイルをリネームします。
TheRoom4の場合はこれで日本語表示ができましたが、これでも日本語表示ができない場合は…頑張って解析を続けるしかないと思います。
名前 | TextMeshPro | m_AssemblyName |
---|---|---|
TheRoom4 | ~v1.0.23 | TextMeshPro.dll |
自作AssetBundle | v1.0.23 | com.unity.textmeshpro.Runtime.dll |
arialuni_sdf_u2018 | v1.3 | Unity.TextMeshPro.dll |
arialuni_sdf_u2019 | v1.4~v3.2 (TMP_FontAsset.version="1.1.0") |
Unity.TextMeshPro.dll |
5-3. NGUI時の対応
// XUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.SetText
namespace XUnity.AutoTranslator.Plugin.Core
{
…省略…
public class AutoTranslationPlugin :
…省略…
{
…省略…
private void SetText( object ui, string text, bool isTranslated, string originalText, TextTranslationInfo info )
{
…省略…
#ifdef _THE_ROOM_TWO_PATCH_
if (ui.GetType() == typeof(UILabel)) {
UILabel label = (UILabel)ui;
if (isTranslated) {
if (label.font.replacement == null) {
UIFont font2 = null;
foreach ( var f in Resources.FindObjectsOfTypeAll() )
{
if ((label.font.name + "2") == f.name) {
font2 = f;
break;
}
}
if (font2 == null)
{
var fonts = Resources.FindObjectsOfTypeAll();
font2 = Instantiate(label.font);
font2.name = label.font.name + "2";
font2.material = null;
font2.dynamicFont = fonts[0]; // Arial
XuaLogger.AutoTranslator.Info(string.Format("made UIFont {0}({1})", font2.name, font2.GetInstanceID() ));
}
else
{
XuaLogger.AutoTranslator.Info(string.Format("found UIFont {0}({1})", font2.name, font2.GetInstanceID() ));
}
label.font.replacement = font2;
}
}
else
{
label.font.replacement = null;
}
}
#endif
ui.SetText( text, info );
…省略…
}
…省略…
}
}
- ゲーム内でUILabel.font.replacementを使用していないことを前提にしている。
使用しているゲームだとフォント(表示)がおかしくなる
- ゲーム内に名前が"2"で終わるUIFontがないことを前提にしている。
nameとname2という後ろに"2"が付いた名前のUIFontと付いていない名前のUIFontがもともとゲーム内に存在していた場合、name2をnameの日本語表示用UIFontとして誤認する。
- ゲーム内のリソースにFontが最低1つは存在していることを前提にしている。
もし無ければ例外発生。日本語表示用UIFontも作成できない。
- ゲーム内(Assembly-CSharp.dll)で定義されているUILabel,UIFontを普通に使っている。
NGUIを使用しているなら、そのゲームのAssembly-CSharp.dllにもUILabel,UIFontがあるはず。しかし、バージョンの違いにより存在しないプロパティなどがあった場合はコンパイルが通らない。
- dnSpyを起動します。既に何か読み込んでいた場合、[File]-[Close All]でAssembly Explorer(左のツリー)を空にします。
- [File]-[Open]で BepInEx\plugins\XUnity.AutoTranslator\XUnity.AutoTranslator.Plugin.Core.dll を開きます。
- [Edit]-[Search Assemblies]でフォーカスが移ったところに XUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.SetText を入力し[enter]キーを押します。
- 入力欄の下に表示された SetText をダブルクリックし、AutoTranslationPluginクラスのメソッド SetText へジャンプします。
- SetTextメソッド内でマウスを右クリック。表示されたメニューの[Edit Method (C#)...]を選択。コード編集画面が開きます。
- 上記コードの#ifdef~#endifの間を#から始まる行を含めずにコピー、SetTextメソッド内のui.SetTextの前へペーストします。
- コード編集画面左下にある[Add Assembly Reference]ボタン(ファイルを開くアイコン)を押し下記ファイルを選択します。(ボタンを押してファイルを選択する…を繰り返します)
BepInEx\core\XUnity.Common.dll TheRoomTwo_Data\Managed\UnityEngine.dll TheRoomTwo_Data\Managed\Assembly-CSharp.dll
- コード編集画面右下にある[Compile]を押します。コンパイル後コード編集画面が閉じられます。([Compile]でコード編集画面が閉じないのであれば何らかのエラーが発生しているはずです。問題を解決してコンパイルが通るようにしてください。)
- [File]-[Save Module...]でダイアログを開き、デフォルトのまま[OK]を押します。その後[File]-[Exit]でdnSpyを閉じます。