XUnity.AutoTranslator による日本語化(自動翻訳化)の手順

これまでにTheRoomの2・3・4をXUnity.AutoTranslatorで日本語化(自動翻訳化)することができました。差し当たり、これで私が日本語化(自動翻訳化)したいゲームはなくなりました。しばらく経って、また自分で日本語化(自動翻訳化)したいゲームが出た頃には今回のことで得た知識を忘れていそうな気がするので新規ゲームへXUnity.AutoTranslatorをセットアップをする場合にどこを見て何を判断すれば良いのか?という視点で再度情報をまとめたいと思います。
(忘れる程時間が経っていると各種ツールのバージョンが上がっていて、これまでのやり方が通じなくなっていた…なんて事は良くあるので無駄になるかも知れませんが…)

1. Unityの判断(Unity以外, x86/x64, Mono/IL2CPP)

XUnity.AutoTranslatorはUnityというゲームエンジンが使用されているゲームでなれば利用することが出来ません。このUnityには種類があり、ゲームが使用しているUnityの種類に合わせたBepInEx(後述)をインストールする必要があるためUnityの種類をまずは判断する必要があります。
※お使いのパソコンやOSのことではありません。ゲームがどの種類の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以外 上記以外
※対象ゲームの実行ファイルを"game.exe"と仮定します。
TheRoom4であれば"OldSins.exe"という実行ファイル名で"OldSins_Data"というフォルダが存在します。
※実行ファイルが32bitか64bitかの判断はこちらをご覧ください。
※私が遊んだことのあるゲームは上記条件にあうものしかありませんでしたが、場合によっては外れるゲームがあるかも知れません。
もし『Unity以外』だった場合はXUnity.AutoTranslatorを利用できないのでこの記事の対象外となります。

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で異なっていることもありプラグインが未対応だと動作しません。) インストール方法
・zipファイルの解凍およびファイル配置
上記zip内のwinhttp.dllとgame.exeが同じフォルダになるように解凍(または解凍後に移動)します。
・BepInExの有効化を確認
通常どおりにゲーム(game.exe)を起動しゲーム内の操作で終了します。
その後エクスプローラー等で"BepInEx\LogOutput.log"(ログファイル)が作成されているかを確認します。
作成されていればメモ帳等で開き重要そうなエラーがないかを確認します。
特に重要そうなエラーがなければBepInExのインストールは完了です。
通常どおりにゲームが起動しない場合:
ゲーム内の操作が効かなくなっている場合は[Alt]+[F4]やタスクマネージャなどでゲームを終了させます。
BepInExのトラブルシューティングに沿って解決を試みます。
(実際にTheRoom2では真っ暗な画面で先に進まなくなりました。こちらに記載されているとおり"BepInEx/config/BepInEx.cfg"の[Preloader.Entrypoint]のTypeをMonoBehaviourへ変更したら解決しました。)
ログファイルが作成されない場合:
ファイルの配置が正しいか(解凍して得られたwinhttp.dllやBepInExフォルダがgame.exeと同じフォルダになっているか?)を再度確認してください。
またUnityの種類(x86/x64, Mono/IL2CPP)とインストールしたzipファイルもあっているか再度確認してください。
間違いが見つからない場合トラブルシューティングに有益な情報がないか探してみてください。
ログに重要そうなエラーがあった場合:
トラブルシューティングに有益な情報がないか探します。
また残っているエラーメッセージで検索し解決策がないかを調べます。
※どうしてもBepInExのインストールに失敗する場合はスタンドアロン版(ReiPatcher)のXUnity.AutoTranslatorを試すという手もあります。

3. XUnity.AutoTranslatorのインストール

続いてインターネットの翻訳サービスを用いてゲーム内テキストの翻訳をしてくれるMOD、XUnity.AutoTranslatorをインストールします。 インストールするファイルはBepInEx版で例によってUnityの種類によって変わってきます(しかしx86とx64は区別なし)。2023年6月時点での最新版は下記のとおりです。
こちらもインストールするのは基本的に最新リリース版で良いと思います。 インストール方法
・zipファイルの解凍およびファイル配置
BepInExのインストールで既にできているBepInExフォルダと上記zip内のBepInExフォルダが一致するように解凍(または解凍後に移動)します。
・XUnity.AutoTranslatorの有効化を確認
通常どおりにゲームを起動しゲーム内の操作で終了します。
その後エクスプローラー等で"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
翻訳先・翻訳元の言語指定です。デフォルトでは日本語→英語になっているので英語→日本語へ変更します。
設定変更後、ゲームを起動しメインメニューなど英語表示のある画面まで進み、しばらく(~1分程)待ちます。
日本語が表示された
日本語化(自動翻訳化)完了です。場合によっては翻訳に関係する設定を変更(長文が翻訳されないときはMaxCharactersPerTranslationを増やすなど)する必要があるかも知れませんが基本的にはこのまま翻訳された日本語で遊ぶことができるはずです。
また[Alt]+[T]で原文⇔訳文を切り替えることができるので、英語がアヤしい時などは利用してみてください。
文字が消えた または 文字が□に変わった
日本語への翻訳は成功したがゲーム内のフォントでは日本語表示に対応していないため発生している現象と思われます。「5. XUnity.AutoTranslatorで日本語表示されないときの対応」へ進んでください。
なお、ゲーム中の操作がしづらい場合は[Alt]+[T]で原文に戻して操作してください。
英語のまま変わらない
原因として下記2点が考えられます。(他にもあるかも知れませんが、現在の私には思いつきません)
①XUnity.AutoTranslatorがテキスト(文字)を取得できていない
対象ゲームがXUnity.AutoTranslatorのサポートしていない方式(フレームワーク)でテキスト出力している…などの理由でテキストが取得できていない。
②翻訳ができていない
テキスト取得はできているが翻訳サービスへ接続できない等の理由で翻訳が失敗している。①よりもこちらの方が可能性が高いと思います。
英語のまま変わらない場合はゲーム画面のまま[Alt]+[0]でXUnity.AutoTranslatorのGUIを表示します。
上図のように"Error'ed translations"が5/5で"Translator status"がShutdownになっている場合は、テキスト取得は成功しているが翻訳が失敗している状態です。
"Translator"を変更し再度テキストを読み込む為にゲーム中の操作で少し画面を切り替えて(メインメニューからオプションメニューへ行った後にメインメニューに戻るなど)ください。
下図のように"Served translations"が増えれば、そのTranslatorが使用できています。ゲーム画面に何らかの変化(日本語表示された/文字が消えた)が起きているはずなので前述に従ってください。
変更後のTranslatorでも"Translator status"がShutdownになる場合は また別のTranslatorを試したり、そもそもインターネットに接続できるかなどWindowsの設定を見直してみてください。
もしテキスト取得が失敗している場合は上図のように"Plugin status"・"Translator status"ともにRunningで"translations"が4つとも0になっているはずです。
単に今まで表示された画面にテキストがなかった(表示された英語は文字情報ではなく画像だった)だけかも知れないので、オプションメニューへ変えてみたりゲーム本編の画面まで進めて見たりして、ゲーム中で様々な画面を表示させてみます。
それでも"translations"が4つとも0で変わらない場合はゲーム内の操作でゲームを終了しログを確認します。
もし何らかのエラーが残っていた場合はそのエラーによってテキスト取得が失敗しているのかも知れないのでエラー内容を調査します。
また設定ファイル内の[TextFrameworks]の全項目をTrueにして変化があるか?などを試してみます。

5. XUnity.AutoTranslatorで日本語表示されないときの対応

XUnity.AutoTranslatorの翻訳結果が表示されない(文字が消える/□が表示される)のはゲーム内のフォントが日本語表示に対応していないために発生しています。
これはゲーム内のフォントを日本語表示可能なフォントへ変更すれば解消することができます。
その変更方法として私が知っているのは下記3つとなります。
①XUnity.AutoTranslatorの機能を利用(TextMeshPro または UGUI のみ)
②XUnity.AutoTranslatorを改造して無理やり日本語表示(NGUI のみ)
③ゲームを改造(リソースの変更など)
①はTheRoom4で行った方法でゲームが使用しているテキストフレームワークが TextMeshPro であれば設定ファイルを変更し外部のフォントを読み込むことができます。(100%可能というわけでは無いようです。ゲーム次第だと思います。)
またドキュメントによればテキストフレームワークが UGUI の場合でも設定ファイルを変更すればフォントを変更できるようです。しかし、こちらは使用したことがないので本記事では扱いません。(設定ファイルの"OverrideFont="で指定可能。コードを流し見る限りWindowsにインストール済のフォント名を指定するようです。)
③は いわゆる日本語化MODで、ゲームを解析してリソース(場合によってはコードも)を変更し日本語表示可能なフォントにする方法です。ゲーム毎の解析が必要なので本記事では扱いません。
②はTheRoom2,3で行った方法で①と③の中間です。TheRoom2を日本語表示させようとdnSpyで適当にイジっていたらNGUIでの日本語表示可能なフォントの簡単な作成方法がわかったのでXUnity.AutoTranslatorを改造して実装した…という方法です。
どの方法で変更するにしても、まずは対象のゲームがどのテキストフレームワークを使用しているかを判断する必要があります。

5-1. テキストフレームワークの判定

下表のとおり設定ファイルを書き換えます。
設定ファイル:BepInEx\config\AutoTranslatorConfig.ini
項目 変更理由等
[Behaviour]
EnableTextPathLogging=True
XUnity.AutoTranslatorがテキストを設定する際、その設定対象の情報をログに出力します。ログ出力の頻度が高めなので、ひと通り調査が終わったらFalseに戻すことをおすすめします。
ゲームを起動し日本語が表示されない(消えた/□になった)画面まで進みゲーム内の操作でゲームを終了。ログを確認します。
例えばTheRoom4ではログに下記が見つかります。XUnity.AutoTranslatorが'TMPro.TextMeshProUGUI'クラスのオブジェクトへテキストを設定しているのでTheRoom4はテキストフレームワークとしてTextMeshProを使用している事がわかります。
[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
TheRoom2では下記となりクラス名は'UILabel'であることがわかります。『UILabel Unity』とGoogleで検索した結果からUILabelはNGUIで使用されているクラス名であることがわかります。
[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
本記事ではこの2種類だけですが、これ以外のクラス名であっても クラス名 + Unity で検索すればテキストフレームワークの判定は可能だと思います。
この後はテキストフレームワーク毎の対応となります。なおTextMeshPro、NGUI以外はわからないので本記事では扱えません。(UGUIは前述の通り"OverrideFont="で何とかなるかも??)

5-2. TextMeshPro時の対応

TextMeshProの場合はXUnity.AutoTranslatorの機能で外部ファイルのフォントへ変更することが可能です。この機能はゲームのリソース(Assets)を後からロードするAssetBundleというUnityの仕組みで作られています。そのため、ゲームと外部ファイルのバージョン(UnityとTextMeshProの両方 特にTextMeshProが重要?)が一致していないと正しく読み込めない場合があります。
XUnity.AutoTranslatorのリリースページにはTMP_Font_AssetBundles.zipというファイル名で2種類のフォントが公開されています。
圧縮ファイル ファイル 用途
TMP_Font_AssetBundles.zip arialuni_sdf_u2018 Unity 2018用
arialuni_sdf_u2019 Unity 2019用
まずは上記ファイルを試してみます。arialuni_sdf_u2018とarialuni_sdf_u2019がgame.exeと同じフォルダへなるようにTMP_Font_AssetBundles.zipを解凍(または解凍後に移動)してください。
次にどちらのファイルを使用するかUnityのバージョンを確認するためログを開きます。ログには下記のような行があり、この場合(TheRoom4)は 2019.4.5f1 であることがわかります。
[Info   :XUnity.AutoTranslator] Loaded XUnity.AutoTranslator into Unity [2019.4.5f1] game.
Unity 2019であることがわかったのでarialuni_sdf_u2019を使用するよう設定ファイルを下表のように書き換えます。(Unity 2018だった場合は arialuni_sdf_u2018 に読み替えてください)
設定ファイル:BepInEx\config\AutoTranslatorConfig.ini
項目 変更理由等
[Behaviour]
OverrideFontTextMeshPro=arialuni_sdf_u2019
FallbackFontTextMeshPro=
テキスト更新時にフォントを指定されたもので上書きします。FallbackFontTextMeshProの利用が推奨されていますがファイルが利用できるか確認するため必ず上書きされるOverrideFontTextMeshProを使用します。なおFallbackFontTextMeshProは空欄にしてください。両方指定されているとAssetBundleの二重ロードで失敗した場合にFallbackFontTextMeshProのみ指定された時と同様の動きとなるためです。
ゲームを起動し日本語が表示されなかった画面まで進みます。
日本語が表示された
arialuni_sdf_u2019が使用できる事が確認できました。これで日本語化(自動翻訳化)完了です。
しかし今はOverrideFontTextMeshProに設定しているのでFallbackFontTextMeshProにだけ指定した場合はどうなるか試してみてください。
特にOverrideFontTextMeshProにだけ指定した時と変化がないようならFallbackFontTextMeshProにだけ指定した状態で使用してください。(FallbackFontTextMeshProの利用が推奨されているため)
文字が消えたり□に戻ってしまう場合はOverrideFontTextMeshProにだけ指定した状態で使用してください。
変わらない(消えたまま/□のまま)
もう一つのファイル(arialuni_sdf_u2018)も同様に試してみてください。
TMP_Font_AssetBundles.zipの2ファイルで日本語表示できない場合はログを確認してください。
もし下行があればファイル配置が異なります。game.exeと同じ場所にarialuni_sdf_u2018とarialuni_sdf_u2019があるか再度確認してください。
[Info   :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from internal Resources API.
もし下記2行が続けてある場合はファイル(AssetBundle)のロードには成功したがその中からフォント(TMPro.TMP_FontAsset)を取り出そうとして失敗しています。(TheRoom4と同症状)
[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
この場合は自分でファイルを作成すれば日本語表示が可能になるかも知れません。
そのためにはゲームが使用しているTextMeshProのバージョンを知る必要があります。
他にもっと良い方法があるかも知れませんが、私はUABEAでゲーム内のフォントを開きデータ構造からバージョンを判断しました。
試しにTMP_Font_AssetBundles.zip内の2ファイルを調べてみます。
UABEAでarialuni_sdf_u2019を開きます。圧縮されているので展開先を聞かれます。[Memory]を選択します。
その後[Info]をクリックします。開いたAsset Infoウィンドウで"ARIALUNI SDF"(Type=MonoBehaviour)を選択し[View Data]をクリックします。
この時に表示されるデータ構造がどのバージョンのTMPro.TMP_FontAssetであれば辻褄が合うかを調べます。
arialuni_sdf_u2019はm_Versionが存在することからTextMeshPro v1.4以降ではないかと思われます。
v1.4以降にはTMP_FontAsset.versionが存在する。
v1.3以前にはTMP_FontAsset.versionが存在しない。
 (Fieldsにも基底クラスのTMP_Assetにも見つからない)
このversionというプロパティはv1.4で追加されてからv3.2まで"1.1.0"で変わらないようです。v1.4~v3.2は バージョンが変わらない=データ構造が変わらない=互換性がある …と思っています(未確認)。
v3.2までversionは"1.1.0"のまま変化なし。
v4.0からTMPro.TMP_FontAssetは非推奨??
 UnityEngine.TextCore.Text.FontAssetが使用される?
同様にarialuni_sdf_u2018はm_CreationSettingsが存在し、m_Versionが存在しないことからTextMeshPro v1.3ではないかと思われます。
v1.3以降にはTMP_FontAsset.creationSettingsが存在する。
v1.2以前にはTMP_FontAsset.creationSettingsが存在しない。
 (かわりにTMP_FontAsset.fontCreationSettingsが存在する)
次にゲームを調べます。まずは調査すべきデータを探します。TypeがMonoBehaviourでNameが" SDF"で終わっているデータを探し[View Data]で見たとき先頭行が"MonoBehaviour Base (TMP_FontAsset)"となっていればアタリです。
条件にあうデータが複数ある場合はどれでも大丈夫です(データ構造は同じはずです)。そのため、UABEAで開くファイルは"game_Data\resources.assets"で大丈夫だと思いますが、もし見つからない場合は"game_Data\sharedassets0.assets"等のファイルも探してみてください。
例としてTheRoom4を調べていきます。
UABEAで"OldSins_Data\resources.assets"を開きます。Asset Infoウィンドウのメニューバーから[View]-[Filter]でType Filterウィンドウを表示。[Deselect all]で全非選択にした後[MonoBehaviour]のみをチェックして[X]で閉じる。いちばん初めのデータが"Anton SDF"と" SDF"で終わっているので[View Data]をクリック。表示されたデータの先頭行が"MonoBehaviour Base (TMP_FontAsset)"となっているのでこのデータの構造を見ていきます。
このデータ構造にはfontCreationSettingsがありm_CreationSettingsがないことからv1.2以前であることがわかります。さらに詳しく見ていくとm_kerningPair内にAscII_Leftという項目がありますがv1.2のドキュメントには記載がありません。最も古いv1.0.26のドキュメントにも記載はありません。
v1.2 : AscII_Leftなし
v1.0.26 : AscII_Leftなし
仕方がないのでUnityEditorのPackage Managerで下記バージョンのTextMeshProをダウンロードしソース(Library\PackageCache\com.unity.textmeshpro@1.0.2x\Scripts\Runtime\TMPro_FontUtilities.cs)を確認しました。
・v1.0.26 : なし (FormerlySerializedAsの記載あり)
・v1.0.25 : なし (FormerlySerializedAsの記載あり)
・v1.0.23 : あり
・v1.0.21 : あり
このことからTheRoom4にはv1.0.23以前のTextMeshProが使用されていると思われます。そのためファイル(AssetBundle)にはTextMeshPro v1.0.23で作成したフォントを入れることにします。(FormerlySerializedAsの記載があることからv1.0の間では互換性があると思います。そのためv1.0.26でも良かったかも知れません。)
データ構造とTextMeshProのバージョンについてわかったことをまとめると下表となります。
データ構造 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
この後はゲームと同じ(もし無ければ近い)バージョンのUnityEditorをインストールしてプロジェクトを作成。そのプロジェクトのPackage ManagerでTextMeshPro(ゲームと同じバージョン)とAssetBundleBrowser(デフォルトのバージョンでOK)をインストール。TextMeshProの"Font Asset Creator"でフォントを作成。"AssetBundle Browser"を起動し出来上がったフォントを入れてBuildすればフォントファイル(AssetBundle)の完成です。
arialuni_sdf_u2019と同じようにファイルを配置・設定ファイルの変更を行い日本語表示できるか確認します。
この自作したファイルでも日本語表示できない場合、またはゲームを調査してTextMeshProがv1.3~v3.2だった場合(本来arialuni_sdf_u2018/u2019で日本語表示できたはず)はAssetBundleの一部書換が必要かも知れません。UABEAでAssetBundleを開き"TMP_FontAsset"(Type=MonoScript)を表示します。この中のm_AssemblyNameにあるdll(下図では"com.unity.textmeshpro.Runtime.dll")が下記フォルダに存在するか確認します。
種類 フォルダ
Mono x86
Mono x64
game_Data\Managed
IL2CPP x86
IL2CPP x64
BepInEx\unhollowed
もし無ければここを存在するdllの名前へ変更することで読み込めるようになるかも知れません。
何というファイル名へ書き換えればよいのか確認するため、ゲーム内のAssetsから"TMP_FontAsset"(Type=MonoScript)を探します。TheRoom4では"OldSins_Data\globalgamemanagers.assets"にありましたが必ずどのゲームもこのファイルにあるとは限らないと思います。なかなか見つからない場合はAssetStudioなどフォルダごと読み込める別ツールを使用して探してください。
上図のとおりゲーム内のTMP_FontAssetではm_AssemblyNameが"TextMeshPro.dll"なのでAssetBundleも同名へ書き換えれば良いことがわかります。
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を閉じます。必要に応じて圧縮前のファイルを削除したり圧縮後のファイルをリネームします。
こうしてm_AssemblyNameを書き換えたファイルで再度日本語表示できるか確認します。
TheRoom4の場合はこれで日本語表示ができましたが、これでも日本語表示ができない場合は…頑張って解析を続けるしかないと思います。
TextMeshPro編の最後にTextMeshProのバージョンとm_AssemblyNameをまとめると下表となります。
名前 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時の対応

NGUIの場合はTextMeshProのようにXUnity.AutoTranslatorの機能でゲーム内のフォントを外部ファイルのフォントで上書きするようなことはできません。そのため、UnityEditor + NGUIで日本語表示可能なフォントを作成しUABEA等でゲーム内のフォントと入れ替える(ゲームのAssetsを書き換える)というのが正攻法だと思います。しかし、単純に入れ替えると言っても整合性を保ちつつ入れ替えなければならないため、ゲームの解析が必要になります。先人たちの情報をもとに頑張れば何とかなる…かもしれませんが大変そうです。
そのため、TheRoom2,3ではXUnity.AutoTranslatorの"XUnity.AutoTranslator.Plugin.Core.dll"に下記コードをdnSpyで追加することで日本語表示可能なフォントへ入れ替えました。
//  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 );

                    …省略…
      }
                    …省略…
   }
}
NGUIのフォントであるUIFontにはdynamicFontというプロパティがあり、これにFontを入れればダイナミックフォントになってくれるようです。TheRoom2,3ではゲームのリソース内にFontがArialしかありませんでしたが、これを入れてみたところOSフォントで代替してくれたようで(見た目はあまり美しくありませんが)日本語表示が可能でした。その後、[Alt]+[T]で原文⇔訳文を切り替えたときにフォントも切り替わるようにしたのが上記コードとなります。
TheRoom2,3以外でもNGUIを使用しているゲームならこのコードが使えるかも知れませんが、かなり決め打ちでコードを書いているので他ゲームだとそのままでは使用できないかも知れません。
私が現在気づいている懸念点は下記のとおりです。
  • ゲーム内で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があるはず。しかし、バージョンの違いにより存在しないプロパティなどがあった場合はコンパイルが通らない。
使用する場合はこの辺りにお気を付けください。
なお、TheRoom2用にインストールした"XUnity.AutoTranslator.Plugin.Core.dll"へ上記コードを追加する手順は下記のとおりです。
  1. dnSpyを起動します。既に何か読み込んでいた場合、[File]-[Close All]でAssembly Explorer(左のツリー)を空にします。
  2. [File]-[Open]で BepInEx\plugins\XUnity.AutoTranslator\XUnity.AutoTranslator.Plugin.Core.dll を開きます。
  3. [Edit]-[Search Assemblies]でフォーカスが移ったところに XUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.SetText を入力し[enter]キーを押します。
  4. 入力欄の下に表示された SetText をダブルクリックし、AutoTranslationPluginクラスのメソッド SetText へジャンプします。
  5. SetTextメソッド内でマウスを右クリック。表示されたメニューの[Edit Method (C#)...]を選択。コード編集画面が開きます。
  6. 上記コードの#ifdef~#endifの間を#から始まる行を含めずにコピー、SetTextメソッド内のui.SetTextの前へペーストします。
  7. コード編集画面左下にある[Add Assembly Reference]ボタン(ファイルを開くアイコン)を押し下記ファイルを選択します。(ボタンを押してファイルを選択する…を繰り返します)
    BepInEx\core\XUnity.Common.dll
    TheRoomTwo_Data\Managed\UnityEngine.dll
    TheRoomTwo_Data\Managed\Assembly-CSharp.dll
  8. コード編集画面右下にある[Compile]を押します。コンパイル後コード編集画面が閉じられます。([Compile]でコード編集画面が閉じないのであれば何らかのエラーが発生しているはずです。問題を解決してコンパイルが通るようにしてください。)
  9. [File]-[Save Module...]でダイアログを開き、デフォルトのまま[OK]を押します。その後[File]-[Exit]でdnSpyを閉じます。

【詳細②】Steam版 The Room 4: Old Sins 日本語化(自動翻訳化)

こちらは詳細内容の記事です。必要ファイルのダウンロードおよび手順を知りたい方は下記記事をご覧ください。
下にも記載したとおり、TheRoom4の日本語化(自動翻訳化)を行うに辺り いろいろと試行錯誤を行いました。
その中で、ゲーム内のリソース(Assets)を書き換えて日本語表示可能なフォントに変更する方法も試し成功しました。
せっかくなので、その事について まとめておきたいと思います。
なお、この記事の最終的な結果は下記パッチを適用することで得られます。
また、リソースの書き換えについて下記を参考にさせていただきました。

対象フォントの選定

リソース内のフォントをAssetStudioでリストアップ(※)すると8個も見つかりました。
名前 コンテナ
Anton SDF Fonts & Materials
Bangers SDF Fonts & Materials
CaslonAntique SDF  
Electronic Highway Sign SDF Fonts & Materials
LiberationSans SDF Fonts & Materials
Oswald Bold SDF Fonts & Materials
Roboto-Bold SDF Fonts & Materials
TheRoom SDF  
※いろいろな方法があるかと思いますが、私はAssetStudioのメニュー[Export]-[Asset list to XML]-[All assets]でxmlに掃き出しテキストエディタGrepしてリストアップしています。
ちょっと多いのでdnSpyで下記コードをXUnity.AutoTranslator.Plugin.Core.dllへ追加し表示されないフォントは対象外とします。
BepInEx\plugins\XUnity.AutoTranslator\XUnity.AutoTranslator.Plugin.Core.dll
XUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.ToggleTranslation

XuaLogger.AutoTranslator.Info("--- START ---");
try
{
    int i = 0;
    foreach (TMPro.TMP_FontAsset f in Resources.FindObjectsOfTypeAll<TMPro.TMP_FontAsset>())
    {
        XuaLogger.AutoTranslator.Info(string.Format("TMPro.TMP_FontAsset[{0}] = {1}", i++, f.name));
    }
}
catch (System.Exception)
{
    XuaLogger.AutoTranslator.Info("Exception!");
}
XuaLogger.AutoTranslator.Info("--- END ---");

※このコードは調査のためだけのコードなのでパッチには含めていません。調査方法を残しておきたくて記事に記載しています。
コードを"Edit Method (C#)..."で追加する際、Compileエラーになる場合があります。
しかし重複に気を付けつつ"Add Assembly Reference (Ctrl+O)"ボタンで下記を読み込めば通るようになります。

BepInEx\plugins\XUnity.AutoTranslator\XUnity.AutoTranslator.Plugin.Core.dll (編集対象)
BepInEx\core\XUnity.Common.dll
BepInEx\core\UnhollowerBaseLib.dll
BepInEx\unhollowed\*
mono\Managed\netstandard.dll

そして、このコードを起動直後のメインメニューで実行した結果は下記のとおりです。

[Info   :XUnity.AutoTranslator] --- START ---
[Info   :XUnity.AutoTranslator] TMPro.TMP_FontAsset[0] = LiberationSans SDF
[Info   :XUnity.AutoTranslator] TMPro.TMP_FontAsset[1] = CaslonAntique SDF
[Info   :XUnity.AutoTranslator] TMPro.TMP_FontAsset[2] = TheRoom SDF
[Info   :XUnity.AutoTranslator] --- END ---

とりあえず、この3個のフォントのみを対象とします。(LiberationSans SDFも未使用な気がしますが表示されているので対象とします)

使用する日本語フォントの選定

どうせなら見た目が近いフォントを使用したいのでそれぞれのフォントについて簡単に調べてみました(個人的な感想含)。
LiberationSans SDF
LiberationSansはLiberationのSans系フォントの意味らしい。
Sans系というのはSans-Serifのことで、セリフ(飾り)が無いって事らしい。ArialやMSゴシックと同類(?)
CaslonAntique SDF
Caslonはセリフ体。その中でもオールド・ローマン体に分類されるらしい。
Antique(アンティーク)は文字通りアンティーク調(?)。『Caslon Antique』で検索すると若干かすれたような見た目のフォントも見つかった。Garamondと同類(?)
TheRoom SDF
TheRoomのために作られたフォント?。セリフ体。トランジショナル・ローマン…のような気がする。
CaslonAntiqueが縦長な文字(長方形)なのに対してこちらは正方形に近い感じ。Centuryに似ている??
上記を踏まえてGoogle Fontsでフォントを探し下記のように決めました。
TheRoom4のフォント 日本語フォント
LiberationSans SDF Noto Sans Japanese (Regular)
CaslonAntique SDF BIZ UDMincho (Regular)
TheRoom SDF Noto Serif Japanese (Regular)

TheRoom4からのエクスポート

対象フォントのTexture2D、MonoBehaviour、Materialがどこにあるかリストアップします。Texture2DはUnityEX、MonoBehaviourとMaterialはUABEAとエクスポートに使用するツールが異なるので別々にまとめると下記となります。このオブジェクトを参考記事に従いエクスポートします。
Texture2D
ファイル名 # オブジェクト名
resources.assets 860 LiberationSans SDF Atlas
resources.assets 865 CaslonAntique SDF Atlas
sharedassets0.assets 6 TheRoom SDF Atlas
MonoBehaviour, Material
ファイル名 # オブジェクト名
resources.assets 8 LiberationSans SDF - Drop Shadow
resources.assets 9 LiberationSans SDF - Metalic Green
resources.assets 10 LiberationSans SDF - Outline
resources.assets 11 LiberationSans SDF - Overlay
resources.assets 12 LiberationSans SDF - Soft Mask
resources.assets 42 LiberationSans SDF Material
resources.assets 43 CaslonAntique SDF Material
resources.assets 3611 LiberationSans SDF
resources.assets 3749 CaslonAntique SDF
sharedassets0.assets 2 TheRoom SDF Material
sharedassets0.assets 83 TheRoom SDF
UnityEX:対象を選択した状態で右クリックし[Export with convert or Raw]を選択
UABEA:対象を選択した状態で[Export Dump]ボタンをクリック。保存先フォルダ選択後に表示される[Select dump type]ダイアログで[UABE text dump]が表示されている状態でOKボタンをクリック。

PointSize,Padding等の確認

エクスポートしたファイルからMonoBehaviourのPointSize, Padding, AtlasWidth, AtlasHeightとMaterialの_TextureHeight, _TextureWidthをまとめると下記となります。
※TheRoom4が使用しているバージョンのTextMeshProにはm_CreationSettingsがないためm_fontInfoからの情報をまとめています。
MonoBehaviour
Name PointSize Padding AtlasWidth AtlasHeight
CaslonAntique SDF 44 5 512 512
LiberationSans SDF 86 9 1024 1024
TheRoom SDF 32 5 512 512
Material
Name _TextureHeight _TextureWidth
CaslonAntique SDF Material 512 512
LiberationSans SDF Material 1024 1024
LiberationSans SDF - Drop Shadow 1024 1024
LiberationSans SDF - Metalic Green 1024 1024
LiberationSans SDF - Outline 1024 1024
LiberationSans SDF - Overlay 1024 1024
LiberationSans SDF - Soft Mask 1024 1024
TheRoom SDF Material 512 512

日本語フォント作成 および ビルド

参考記事に従い日本語フォントを作成します。インストールするUnity、TextMeshProのバージョンはTheRoom4にあわせ下記にします。
Unity 2019.4.5f1
TextMeshPro 1.0.23
Font Asset Creatorの設定値は下表のとおりです。
BIZUDMincho-Regular SDF(CaslonAntique SDF用)
Font Source BIZUDMincho-Regular.ttf
Font Size Custom Size : 44
Font Padding 5
Packing Method Fast
Atlas Resolution 8192 x 4096 ※2
Character Set Characters from File
Character File JpFontText_utf-8.txt
Font Style Normal : 2
Font Render Mode Distance Field 16
Get Kerning Pairs
NotoSansJP-Regular SDF(LiberationSans SDF用)
Font Source NotoSansJP-Regular.ttf
Font Size Custom Size : 32 ※1
Font Padding 5 ※1
Packing Method Fast
Atlas Resolution 4096 x 4096 ※2
Character Set Characters from File
Character File JpFontText_utf-8.txt
Font Style Normal : 2
Font Render Mode Distance Field 16
Get Kerning Pairs
NotoSerifJP-Regular SDF(TheRoom SDF)
Font Source NotoSerifJP-Regular.otf
Font Size Custom Size : 32/td>
Font Padding 5
Packing Method Fast
Atlas Resolution 4096 x 4096 ※2
Character Set Characters from File
Character File JpFontText_utf-8.txt
Font Style Normal : 2
Font Render Mode Distance Field 16
Get Kerning Pairs
※1:LiberationSans SDFの値に合わせればPointSize=86,Padding=9ですが大き過ぎると感じたためTheRoom SDFと同じ値としました。(おそらく使われないフォントですし…)
※2:無条件で最大値(8192 x 8192)にしても良かったかも知れませんが使用メモリ量に多少は影響するかもしれないので収まる範囲で最小の大きさにしました。この時、Font Render ModeをHinted SmoothでAtlasWidth,AtlasHeightを調整し、本番はDistance Field 16でレンダリングすることで多少は時短になりました。
オブジェクトの作成(3個)およびビルドは参考記事のまま特に変更はありません。

自作ゲーム(?)からのエクスポートおよびリネーム

参考記事に従い、ビルドした自作ゲーム(?)から対象フォントのTexture2D・MonoBehaviour・Materialをエクスポートします。また上書きするためにTheRoom4にあわせてリネームします。エクスポートするオブジェクトおよびリネームの対応は下表のとおりです。
オブジェクト名 エクスポートされたファイル名 ※ リネーム後のファイル名
BIZUDMincho-Regular SDF Atlas BIZUDMincho-Regular SDF Atlas.tex.dds CaslonAntique SDF Atlas.tex.dds
BIZUDMincho-Regular SDF Material BIZUDMincho-Regular SDF Material-sharedassets0.assets-4.txt CaslonAntique SDF Material-resources.assets-43.txt
BIZUDMincho-Regular SDF BIZUDMincho-Regular SDF-sharedassets0.assets-10.txt CaslonAntique SDF-resources.assets-3749.txt
NotoSansJP-Regular SDF Atlas NotoSansJP-Regular SDF Atlas.tex.dds LiberationSans SDF Atlas.tex.dds
NotoSansJP-Regular SDF Material NotoSansJP-Regular SDF Material-sharedassets0.assets-3.txt LiberationSans SDF Material-resources.assets-42.txt
NotoSansJP-Regular SDF NotoSansJP-Regular SDF-sharedassets0.assets-11.txt LiberationSans SDF-resources.assets-3611.txt
NotoSerifJP-Regular SDF Atlas NotoSerifJP-Regular SDF Atlas.tex.dds TheRoom SDF Atlas.tex.dds
NotoSerifJP-Regular SDF Material NotoSerifJP-Regular SDF Material-sharedassets0.assets-2.txt TheRoom SDF Material-sharedassets0.assets-2.txt
NotoSerifJP-Regular SDF NotoSerifJP-Regular SDF-sharedassets0.assets-12.txt TheRoom SDF-sharedassets0.assets-83.txt
※環境によって名称が若干変わります。

MonoBehaviour・Materialの書き換え

MonoBehaviour・Materialの内容が自作ゲーム(?)のままなので必要な箇所のみTheRoom4にあわせて書き換えます。参考記事では MultiReplace というツールとその設定ファイルで書き換えられていますが、そのまま使用できないので手動で書き換えます。(_TextureHeight・_TextureWidthのみを書き換えるファイルには利用させていただきました)
参考記事と設定ファイルに同封されていたメモをもとにTheRoom4(TextMeshPro v1.0.23)での変更箇所は下記としました。(下記項目をTheRoom4の値で上書きしていく)
MonoBehaviour
  • ① m_Scriptのm_FileID, m_PathID
  • ② m_Name
  • ③ hashCode
  • ④ materialのm_FileID, m_PathID
  • ⑤ materialHashCode
  • ⑥ m_fontInfo.name
  • ⑦ atlasのm_FileID, m_PathID
対象ファイル
  • CaslonAntique SDF-resources.assets-3749.txt
  • LiberationSans SDF-resources.assets-3611.txt
  • TheRoom SDF-sharedassets0.assets-83.txt
Material
  • ① m_Name
  • ② m_Shaderのm_FileID, m_PathID
  • ③ m_SavedProperties.m_TexEnvs[0~4]のm_FileID, m_PathID
    (ほとんどの項目が0だが_MainTexのみ設定があった)
対象ファイル
  • CaslonAntique SDF Material-resources.assets-43.txt
  • LiberationSans SDF Material-resources.assets-42.txt
  • TheRoom SDF Material-sharedassets0.assets-2.txt
下記MaterialについてはTheRoom4からエクスポートしたファイルをそのままコピーして_TextureHeight・_TextureWidthのみ日本語フォントに合わせた4096x4096へ書き換えます。
  • LiberationSans SDF - Drop Shadow-resources.assets-8.txt
  • LiberationSans SDF - Metalic Green-resources.assets-9.txt
  • LiberationSans SDF - Outline-resources.assets-10.txt
  • LiberationSans SDF - Overlay-resources.assets-11.txt
  • LiberationSans SDF - Soft Mask-resources.assets-12.txt
これには参考記事の設定ファイルが利用できます。
参考記事からダウンロードできる設定ファイルを適用したMultiReplaceで置換リストを[B TMP_FontMaterial]-[2:// H4096W4096]に合わせ上記5ファイルをファイル名にドロップし[置換]をクリックします。

TheRoom4へのインポート

参考記事に従い日本語フォントのTexture2D・MonoBehaviour・Materialをインポートします。
Texture2D
エクスプローラー等でTheRoom4からエクスポートした際にできた下記フォルダ構造を崩さずに、それぞれのファイルを自作ゲーム(?)からエクスポートしリネームしたファイルで上書きします。

  Unity_Assets_Files
    ├─resources
    │  └─Textures
    │      └─res_resources
    │              CaslonAntique SDF Atlas.tex.dds
    │              LiberationSans SDF Atlas.tex.dds
    │
    └─sharedassets0
        └─Textures
            └─res_sharedassets0
                    TheRoom SDF Atlas.tex.dds

その後resources.assetをUnityEXで開いて[Import files]ボタンをクリック。同様にsharedassets0.assetをUnityEXで開いて[Import files]ボタンをクリックすればTexture2Dのインポートは完了です。
MonoBehaviour, Material
resources.assetsまたはsharedassets0.assetsをUABEAで開きます。インポート対象を選択(複数可)した状態で[Import Dump]ボタンをクリック。自作ゲーム(?)からエクスポートし書換を行ったファイルのあるフォルダを選択。その後表示される[Select dump type]ダイアログで[UABE text dump]が表示されている状態でOKボタンをクリック。[Batch import]が表示されるので確認の後OKボタンをクリック。以上で最初に選択したオブジェクトのインポートは完了です。同様の操作を繰り返し下記すべてをインポートします。
ファイル名 # オブジェクト名
resources.assets 8 LiberationSans SDF - Drop Shadow
resources.assets 9 LiberationSans SDF - Metalic Green
resources.assets 10 LiberationSans SDF - Outline
resources.assets 11 LiberationSans SDF - Overlay
resources.assets 12 LiberationSans SDF - Soft Mask
resources.assets 42 LiberationSans SDF Material
resources.assets 43 CaslonAntique SDF Material
resources.assets 3611 LiberationSans SDF
resources.assets 3749 CaslonAntique SDF
sharedassets0.assets 2 TheRoom SDF Material
sharedassets0.assets 83 TheRoom SDF

日本語フォント化完了

以上でTheRoom4の日本語フォント化が完了です。XUnity.AutoTranslatorと組み合わせることで下記のように日本語が表示されるようになります。
ここまでやった後にXUnity.AutoTranslatorでTheRoom4に読み込ませることのできるフォント(AssetBundle)の作成方法がわかりました。
resources.asset#894には"English"という名前のTextAssetがあるので、これを翻訳できればBepinExもXUnity.AutoTranslatorも不要で日本語化ができると思うのですが、私に翻訳はできません。
翻訳サービスを利用するならXUnity.AutoTranslatorが便利で、XUnity.AutoTranslatorを使用するならAssetBundleでの日本語フォント化の方が導入しやすい…と思い、こちらは作っただけでほとんど使用して(遊んで)いません。

ただせっかくなので記事を書かせていただきました。どなたかの そして なにかの参考になれば幸いです。

Steam版 The Room 4: Old Sins 日本語化(自動翻訳化)

Steam版 The Room 4: Old Sins も日本語化(自動翻訳化)することができました。ここでは簡単に手順のみ記載したいと思います。詳しくは下記をご覧ください。
Steam版 The Room Three 以前の日本語化(自動翻訳化)は下記をご覧ください。
① BepInEx(UnityIL2CPP x64 v6.0.0pre.1)のインストール
まずはIL2CPP用のBepInExをインストールします。設定はデフォルトのままで大丈夫です。
② XUnity.AutoTranslator(BepInEx IL2CPP v5.2.0)のインストールおよび設定
次にBepInEx版IL2CPP用のXUnity.AutoTranslatorをインストールします。AutoTranslatorConfig.iniファイル[General]のLanguage・FromLanguageを変更して英語→日本語にします。また[Service]のEndpointを好みや環境に合わせて変更します。
BepInEx\config\AutoTranslatorConfig.ini
[Service]
Endpoint=DeepLTranslate
FallbackEndpoint=

[General]
Language=ja
FromLanguage=en

…省略…
③ 日本語表示用フォントの適用
The Room 4で使用されているフォントでは日本語の表示ができないため、XUnity.AutoTranslatorのフォント上書機能を利用して日本語表示を行います。 下記ファイルをダウンロード・解凍し bizudmincho_TheRoom4 を OldSins.exe と同じフォルダへ配置してください。また AutoTranslatorConfig.ini ファイル [Behaviour] の OverrideFontTextMeshPro に bizudmincho_TheRoom4 を追記してください。なお FallbackFontTextMeshPro は空欄のままにしておいてください。
BepInEx\config\AutoTranslatorConfig.ini

…省略…    
[Behaviour]
…省略…    
OverrideFontTextMeshPro=bizudmincho_TheRoom4
FallbackFontTextMeshPro=
…省略…

以上でSteam版 The Room 4: Old Sinsの日本語化(自動翻訳化)は完了です。 ゲームを起動するとEndpointで指定されたサービスを用いて翻訳され日本語が表示されるはずです。


余談:FallbackFontTextMeshProは空欄のまま??
上記手順でFallbackFontTextMeshProは空欄のままとしたのには訳があります。
当初FallbackFontTextMeshProのみにフォントを指定して遊んでいたのですが一部表示が欠けている事に気づきました(欠けたのは[ESC]キーを押した時のタイトル『ポーズ中』など)。そのためOverrideFontTextMeshProにもフォントを指定したのですが改善しません。ログを確認すると下記のとおり2回目(Override用)のロードで失敗していました。

[Info   :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from asset bundle.
[Info   :XUnity.AutoTranslator] Loaded TextMesh Pro font uses version: Unknown
[Info   :XUnity.AutoTranslator] Loaded fallback font for TextMesh Pro: bizudmincho_TheRoom4
[Info   :XUnity.AutoTranslator] Loaded XUnity.AutoTranslator into Unity [2019.4.5f1] game.
[Info   :Unhollower] Registered mono type XUnity.AutoTranslator.Plugin.Core.Il2CppManagedEnumerator in il2cpp domain
[Info   :XUnity.AutoTranslator] Skipping plugin scan because no plugin-specific translations has been registered.
…省略…
[Info   :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from asset bundle.
[Error  :     Unity] The AssetBundle 'C:\...\bizudmincho_TheRoom4' can't be loaded because another AssetBundle with the same files is already loaded.
[Warning:XUnity.AutoTranslator] Could not load asset bundle while loading font: C:\...\bizudmincho_TheRoom4
OverrideFontTextMeshProとFallbackFontTextMeshProの両方に同じフォントを指定した場合、多重ロードができないため必ず2回目(Override用)が失敗しFallbackFontTextMeshProのみを指定した時と同じ動きとなるようです。
なお、この2つの設定項目についてXUnity.AutoTranslatorのドキュメントでは下記のように記載されています。(訳:DeepL翻訳)
OverrideFontTextMeshPro
代わりにFallbackFontTextMeshProの使用を検討してください。 テキストコンポーネントを更新する際に、テキストに使用されるフォントを上書きします。 注:TextMeshProに対してのみ機能します。
Consider using FallbackFontTextMeshPro instead. Overrides the fonts used for texts when updating text components. NOTE: Only works for TextMeshPro
FallbackFontTextMeshPro
特定の文字に対応していない場合に、TextMeshProのフォールバックフォントを追加します。OverrideFontTextMeshProよりも推奨されます。
Adds a fallback font for TextMeshPro in case a specific character is not supported.This is recommended over OverrideFontTextMeshPro
XUnity.AutoTranslatorのバージョンやゲームによっても動きが変わるかも知れないので一概には言えませんが下記のように運用するのが良いと思います。
  • ① FallbackFontTextMeshProのみにフォントを指定して試してみる。
  • ② ①で不都合が生じたらOverrideFontTextMeshProのみにフォントを指定する。
    (FallbackFontTextMeshProを空欄に戻すのを忘れないこと)
なお上記の私が確認した表示の欠けはOverrideFontTextMeshProのみにフォント指定することで改善されました。

【詳細】Steam版 The Room 4: Old Sins 日本語化(自動翻訳化)

こちらは詳細内容の記事です。必要ファイルのダウンロードおよび手順を知りたい方は下記記事をご覧ください。
The Room Two, Three と日本語フォントへ強制変更するコードをXUnity.AutoTranslatorへ追加するというアヤしい方法ながらも何とか日本語化(自動翻訳化)に成功しました。 そしてThe Room 4: Old Sinsです。最新作なのできっとTextMeshProが使われていて、難なくXUnity.AutoTranslatorで翻訳できるんだろうなぁ…と思っていたのですがハマりました。
最終的にはOverrideFontTextMeshProで指定できるフォントを自作し日本語化(自動翻訳化)は出来たのですが、その過程でいろいろと試したことや分かったことがありますのでココに残したいと思います。

分かった事のまとめ

フォント(より正確にはTextMeshProのフォントを含むAssetBundle)のTMP_FontAssetにあるm_AssemblyNameはゲームのリソース(Assets)内にあるm_AssemblyNameに合わせないとOverrideFontTextMeshProに利用できない。以降、ほぼ時系列で試したことや分かったことを記載していきます。

TheRoom4は『OverrideFontTextMeshPro = arialuni_sdf_u2019』が効かない

OverrideFontTextMeshProというのはXUnity.AutoTranslatorでTextMeshProのフォントを置き換える時に指定する設定項目です。
arialuni_sdf_u2019というのはXUnity.AutoTranslatorのリリースページからダウンロードできるTMP_Font_AssetBundles.zipに入っているフォントの一つでUnity v2019用です。
この設定でTextMeshProのフォントが置き換われば、それで終わったのですが…。
なおTheRoom4にXUnity.AutoTranslatorを導入する際の基本情報は下記のとおりです。
  • TheRoom4はIL2CPPでコンパイルされている(il2cpp_dataフォルダがある)
  • TheRoom4へBepInEx 6.0.0-pre.1をデフォルト設定で導入できる。
  • TheRoom4へXUnity.AutoTranslator(BepInEx版IL2CPP用)を難なく導入できる。
  • TheRoom4はUnity [2019.4.5f1]で制作されている。
XUnity.AutoTranslatorを導入し最低限の設定を済ませてゲームを起動すると…日本語へ翻訳されたが日本語が表示できるフォントではないので文字のない(もう見慣れた)メインメニューが表示されます。
ここでOverrideFontTextMeshPro・FallbackFontTextMeshProにarialuni_sdf_u2019を指定して日本語表示されれば終了だったのですが…ダメでした。

とりあえずTextMeshProが使用されているかを確認します。下記デバック用の設定を行い再度ゲームを起動します。
  • コンソール画面の表示
    BepInEx.cfg
    
    [Logging.Console]
    Enabled = true
    
  • Unityのログもファイルに残す(falseのままだとコンソール画面への表示だけ)
    BepInEx.cfg
    
    [Logging.Disk]
    WriteUnityLog = true
    
  • テキストを設定したオブジェクトのクラス名やパスを出力(XUnity.AutoTranslator)
    AutoTranslatorConfig.ini
    
    [Behaviour]
    EnableTextPathLogging=True
    
ログ(またはコンソール画面)を確認すると下記出力がありTheRoom4がTextMeshProを使用しているのが分かります。

[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
ではなぜOverrideFontTextMeshProが効かないのか?フォント(AssetBundle)ロード時のログが残っていました。

[Info   :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from asset bundle.
[Warning:     Unity] The referenced script (TMPro.TMP_FontAsset) on this Behaviour is missing!
[Warning:     Unity] The referenced script on this Behaviour (Game Object '<null>') is missing!
[Error  :XUnity.AutoTranslator] Could not find the TextMeshPro font asset: arialuni_sdf_u2019
上記ログを踏まえてXUnity.AutoTranslatorのソースを見ると下記のことが分かります。
  • "arialuni_sdf_u2019"というファイルは存在してる。(パス指定をミスったりしてない)
  • AssetBundle(ファイル名"arialuni_sdf_u2019")のロードには成功している。
  • ロードしたAssetBundleからTMP_FontAssetを取り出そうとしたら失敗した。※
    ※ソースだけではUnityTypes.TMP_FontAsset == nullかも知れなかったので、のちにdnSpyでも調査。LoadAllAssetsで0個の配列が返されFirstOrDefaultでfont=nullとなっていた。

      public static UnityEngine.Object GetTextMeshProFont( string assetBundle )
      {
         UnityEngine.Object font = null;

         var overrideFontPath = Path.Combine( Paths.GameRoot, assetBundle );
         if( File.Exists( overrideFontPath ) )
         {
            // ↓の出力があるのでファイルは見つかっている
            XuaLogger.AutoTranslator.Info( "Attempting to load TextMesh Pro font from asset bundle." );

            // ↓の出力がないのでLoadFromFile(またはCreateFromFile)は成功している
            AssetBundle bundle = null;
            if( UnityTypes.AssetBundle_Methods.LoadFromFile != null )
            {
               bundle = (AssetBundle)UnityTypes.AssetBundle_Methods.LoadFromFile.Invoke( null, new object[] { overrideFontPath } );
            }
            else if( UnityTypes.AssetBundle_Methods.CreateFromFile != null )
            {
               bundle = (AssetBundle)UnityTypes.AssetBundle_Methods.CreateFromFile.Invoke( null, new object[] { overrideFontPath } );
            }
            else
            {
               XuaLogger.AutoTranslator.Error( "Could not find an appropriate asset bundle load method while loading font: " + overrideFontPath );
               return null;
            }
            if( bundle == null )
            {
               XuaLogger.AutoTranslator.Warn( "Could not load asset bundle while loading font: " + overrideFontPath );
               return null;
            }

            // この後のエラー出力があるのでココでfont = null
            if( UnityTypes.TMP_FontAsset != null )
            {
               if( UnityTypes.AssetBundle_Methods.LoadAllAssets != null )
               {
#if MANAGED
                  var assets = (UnityEngine.Object[])UnityTypes.AssetBundle_Methods.LoadAllAssets.Invoke( bundle, new object[] { UnityTypes.TMP_FontAsset.UnityType } );
#else
                  var assets = (UnhollowerBaseLib.Il2CppReferenceArray<UnityEngine.Object>)UnityTypes.AssetBundle_Methods.LoadAllAssets.Invoke( bundle, new object[] { UnityTypes.TMP_FontAsset.UnityType } );
#endif
                  font = assets?.FirstOrDefault();	// ココでnullとなっていた(dnSpyで確認)
               }
               else if( UnityTypes.AssetBundle_Methods.LoadAll != null )
               {
#if MANAGED
                  var assets = (UnityEngine.Object[])UnityTypes.AssetBundle_Methods.LoadAll.Invoke( bundle, new object[] { UnityTypes.TMP_FontAsset.UnityType } );
#else
                  var assets = (UnhollowerBaseLib.Il2CppReferenceArray<Unityengine.Object>)UnityTypes.AssetBundle_Methods.LoadAll.Invoke( bundle, new object[] { UnityTypes.TMP_FontAsset.UnityType } );
#endif
                  font = assets?.FirstOrDefault();
               }
            }
         }
         else
         {
            XuaLogger.AutoTranslator.Info( "Attempting to load TextMesh Pro font from internal Resources API." );

            font = Resources.Load( assetBundle );
         }

          // ↓のエラー出力があるのでココまででfontはnullになっている
         if( font != null )
         {
            var versionProperty = UnityTypes.TMP_FontAsset_Properties.Version;
            var version = (string)versionProperty?.Get( font ) ?? "Unknown";
            XuaLogger.AutoTranslator.Info( $"Loaded TextMesh Pro font uses version: {version}" );

            if( versionProperty != null && Settings.TextMeshProVersion != null && version != Settings.TextMeshProVersion )
            {
               XuaLogger.AutoTranslator.Warn( $"TextMesh Pro version mismatch. Font asset version: {version}, TextMesh Pro version: {Settings.TextMeshProVersion}" );
            }

            GameObject.DontDestroyOnLoad( font );
         }
         else
         {
            XuaLogger.AutoTranslator.Error( "Could not find the TextMeshPro font asset: " + assetBundle );
         }

         return font;
      }

arialuni_sdf_u2019にTMP_FontAssetがあるのかUABEAで確認すると…下画面の通りにちゃんとあります。 コレでなんでTMP_FontAssetの取り出しに失敗するのか? 謎
しかしTextMeshProを使用していることは確定したのでTMP_FontAssetの取り出しに成功するファイルがないかarialuni_sdf_u2018(Unity v2018用)や手当たり次第に様々な場所からダウンロードしたファイルも試してみましたが全滅でした。

TheRoom4が使用しているTextMeshProのバージョンが古い(v1.0.23以前)

AssetBundleでのフォント置換が行き詰ってしまったので、The Room Two, Threeのように日本語フォントへ強制変更するコードが追加できないか調査を開始。
TextMeshProのドキュメントを見るとTMP_FontAssetにCreateFontAssetというメソッドを発見。これが使えないか試そうとBepInEx\unhollowed\TextMeshPro.dllを見るとCreateFontAssetというメソッドがない。il2cppだから見れないだけで本当はあるのかな?と思いXuaLogger.AutoTranslatorの既存コードをマネてメソッド取得を試みるも失敗。GetCharactersなど見えているメソッドは取得できるので追加したコードにミスがあるわけではなく、見えない=本当にない という事のようでした。
ちなみにCreateFontAssetがないTextMeshProがあり得るのかバージョンを遡るとv1.3以前ならCreateFontAssetがないようでした。

CreateFontAsset以外にコードでUnityEngine.FontからTMP_FontAssetを作成する方法が見つからず(思いつかず)また行き詰ってしまいました。 そのため大変そうですが下記記事を参考にゲームのリソース(Assets)を書き換えてフォントを日本語化させる方法を試してみる事にしました。 (※こちらの方法でもフォントの日本語化に成功しています。せっかくなので後日記事にするかも知れません。)
この中で、TextMeshProのMonoBehaviourファイルにm_CreationSettingsセクションがあり、その中のPointSizeおよびPaddingの数値を元にフォントを作成する…という内容が記載されていますが、m_CreationSettingsというセクションがTheRoom4にはありません。
PointSize, Paddingという数値はありますがm_fontInfoというセクション内だけで他に存在しません。またm_CreationSettingsに似た名前としてfontCreationSettingsというセクションがあります。
ドキュメントを確認するとv1.2以前はm_CreationSettingsではなくfontCreationSettingsだったようです。
さらにTheRoom4からエクスポートしたTextMeshProのMonoBehaviourファイルにはm_kerningPair内にAscII_Leftという項目がありますがコレもバージョンアップにより変更になった項目のようです。
しかし最も古いv1.0.26のドキュメントにも記載はありません。
仕方がないので対象バージョンをPackage Managerでダウンロードしソース(Library\PackageCache\com.unity.textmeshpro@1.0.2x\Scripts\Runtime\TMPro_FontUtilities.cs)を確認しました。
v1.0.26 : なし (FormerlySerializedAsの記載あり)
v1.0.25 : なし (FormerlySerializedAsの記載あり)
v1.0.23 : あり
v1.0.21 : あり
以上により、TheRoom4が使用しているTextMeshProはv1.0.23以前であることが分かりました。そのためTextMeshPro v1.0.23で日本語フォントを作成しました。
ちなみにTheRoom4が使用しているUnityはv2019.4.5f1で、このバージョンのUnityと同時にインストールされるTextMeshProはv2.0.1でした。

AssetBundleのTMP_FontAssetにあるm_AssemblyNameはゲーム内と同じにする必要がある

ゲームのAssetsを書き換えてフォントを日本語化させる方法を試すにあたってUnity Editorをインストールしました。
Package ManagerでAssetBundleBrowserもインストールし下記組み合わせのAssetBundleを作成してOverrideFontTextMeshProで使用できるか試しましたが全滅でした。
  • Unity v2019.4.5f1 + TextMeshPro v2.0.1
  • Unity v2019.4.5f1 + TextMeshPro v1.3
  • Unity v2019.4.5f1 + TextMeshPro v1.2
  • Unity v2019.4.5f1 + TextMeshPro v1.1
  • Unity v2019.4.5f1 + TextMeshPro v1.0.26
  • Unity v2019.4.5f1 + TextMeshPro v1.0.23
  • Unity v2019.4.5f1 + TextMeshPro v1.0.21
結構自信のあったv1.0.23、v1.0.21でもダメでした。

結局、ゲームのAssetsを書き換えてフォントを日本語化させる方法がうまくいったので、OverrideFontTextMeshProが利用できなかったのは謎のまま終わりにしようと思ったのですが、ブログを記載するためにメモを整理していたら下記を確認していないことに気づきました。
  • ① ゲームのAssets内に"TMP_FontAsset"という名前のオブジェクトが存在するか?(AssetBundleにはあった)
  • ② もしゲーム内にも存在した場合、AssetBundle内の内容とどこが違うのか?
  • ③ もしゲーム内にも存在した場合、AssetBundle内のTMP_FontAssetをゲーム内のTMP_FontAssetで上書きすればOverrideFontTextMeshProで使用できないか?
①:globalgamemanagers.assets#218に"TMP_FontAsset"という名前のオブジェクトが1つだけありました。
こういうときはフォルダで読み込めるAssetStudioが楽です。StreamingAssetsがあると重いので一時避難が必要ですが…。また、下のようにあらかじめ全Assetのリストを保存しておくと便利です。
②:Unity v2019.4.5f1 + TextMeshPro v1.0.23で作成したAssetBundleとゲーム内のTMP_FontAssetの内容は下記の通りです。
異なるのはm_AssemblyNameだけです。どこのハッシュ値なのか分かりませんがm_PropertiesHashまで一致しています。なお途中までしか表示されていない…というわけではなくバイナリ(Raw)で比較してもm_AssemblyNameしか違いがありません。
③:Unity v2019.4.5f1 + TextMeshPro v1.0.23で作成したAssetBundleにゲーム内のTMP_FontAssetを上書きしたところOverrideFontTextMeshProで使用できるようなりました。
ちなみにarialuni_sdf_u2019にゲーム内のTMP_FontAssetを上書きしたところTMP_FontAssetの取得に成功しました。 下記ログの"Loaded TextMesh Pro font uses version:"が取得成功のメッセージです。 新バージョンのデータを旧バージョンのデータ構造で参照することになるため矛盾が生じ、例外が発生しまくりますが…。

[Info   :XUnity.AutoTranslator] Attempting to load TextMesh Pro font from asset bundle.
[Info   :XUnity.AutoTranslator] Loaded TextMesh Pro font uses version: Unknown
[Warning:XUnity.AutoTranslator] An error occurred while handling the UI discovery.
UnhollowerBaseLib.Il2CppException: System.NullReferenceException: Object reference not set to an instance of an object.
あとm_PropertiesHashが異なるとどうなるか気になったのでOverrideFontTextMeshProで利用できるようにしたUnity v2019.4.5f1 + TextMeshPro v1.0.23のAssetBundleのm_PropertiesHashをオールゼロに書き換えて試してみました。
普通に使えました。m_PropertiesHashによるチェックなどは(v2019.4.5f1では)無いようです。

最後に

ほぼ諦めたOverrideFontTextMeshProによるフォント指定で日本語化(自動翻訳化)することができました。はじめはOverrideFontTextMeshProが利用できない原因がil2cppにあるのではないかと思い、かなり見当違いなことも沢山試しました…。 最終的にはUnity v2019.4.5f1 + TextMeshPro v1.0.23で作成したAssetBundleのTMP_FontAssetに記載されたm_AssemblyNameを"com.unity.textmeshpro.Runtime.dll"から"TextMeshPro.dll"へ変更しただけでOverrideFontTextMeshProで利用可能となりました。
おそらく、このm_AssemblyNameがTMP_FontAssetクラスのあるdllの指定で、com.unity.textmeshpro.Runtime.dllがなかったのでTMP_FontAssetが取得できなかったのだと思います。 Unity・TextMeshPro両方のバージョンをゲームと合わせた環境でフォント(AssetBundle)を作成すれば自然にゲームと同じ値となるはずですが、TheRoom4の場合は何故か"com.unity.textmeshpro.Runtime.dll"を"TextMeshPro.dll"として実装しているためOverrideFontTextMeshProに利用できなかったのだと思います。
(Unityのバージョンに対し、妙に古いTextMeshProを使用していることから、Package Managerを使用せず手動でTextMeshProをセットアップしているような気がします。)
もし 他のゲームでXUnity.AutoTranslatorを使用しようとする時にUnity・TextMeshPro両バージョンをゲームと合わせた環境で作成したフォント(AssetBundle)でもOverrideFontTextMeshProに利用できない場合はAssetBundle内のTMP_FontAssetに記載されたm_AssemblyNameも確認して見てください。

Steam版 The Room Three 日本語化(自動翻訳化)

Steam版 The Room ThreeもThe Room Twoと同じ方法で日本語化(自動翻訳化)することができました。The Room Twoの日本語化(自動翻訳化)については下記をご覧ください。

① BepInEx(x86 v5.4.21)のインストールおよび設定

まずはBepInExをインストールします。The Room Twoとは異なりデフォルト設定のままで大丈夫です。

② XUnity.AutoTranslator(BepInEx v5.2.0)のインストールおよび設定

次にBepInEx版のXUnity.AutoTranslatorをインストールします。The Room Twoと同じようにAutoTranslatorConfig.iniファイル[General]のLanguage・FromLanguageと好みや環境により[Service]のEndpointを変更します。

BepInEx\config\AutoTranslatorConfig.ini
[Service]
Endpoint=DeepLTranslate
FallbackEndpoint=

[General]
Language=ja
FromLanguage=en

…省略…
③ XUnity.AutoTranslator.Plugin.Core.dllの改造

ゲームを起動するとXUnity.AutoTranslatorにより翻訳されますが日本語が表示できないために文字が消えてしまいます。([Alt]+[T]で英語表示に戻せます) 無理やり日本語を表示させるためにXUnity.AutoTranslator.Plugin.Core.dllを改造します。

パッチ適用方法は同封のreadme.txtをご覧ください。

以上でSteam版 The Room Threeの日本語化(自動翻訳化)が完了です。

Steam版 The Room Two 日本語化(自動翻訳化):詳細

こちらは詳細内容の記事です。必要ファイルのダウンロードおよび手順を知りたい方は下記記事をご覧ください。

Steam版 The Room Two 日本語化(自動翻訳化)において、XUnity.AutoTranslatorの導入まではスムーズに進みましたが日本語表示を行うためには時間がかかりました。
日本語表示を行うために調べてわかったことをメモします。

The Room TwoはUnity 5.3.4f1で制作されている

The Room Twoのリリース日は2016年7月5日となっています。そのためか使用されているUnityは結構古めのバージョンです。XUnity.AutoTranslatorで日本語表示できない…と調べるとTextMeshProに関することが良く見つかったので色々と試してみたのですが、このバージョンでは無関係(サポートされる前)だったぽいです。

The Room Twoは文字表示にNGUIを使用している

XUnity.AutoTranslatorが対応しているText FrameworksにはUGUI、NGUI、TextMeshProなどがあるようです。TextMeshProはUnityが古いのであり得ないとして、The Room Twoはいったいどのフレームワークを使用しているのか?調査にはdnSpyを用いました。

dnSpyの"Edit Method (C#)..."でXUnity.AutoTranslator.Plugin.Core.dllへデバック出力を追加してテキストを取得/設定しているオブジェクトのクラス名を表示させてみると、ゲーム起動直後のメインメニューではすべてUILabelでした。 また、UILabelクラスにはfontというUIFontクラスのプロパティがあるということもわかりました。そして、UILabel,UIFontというクラス名からThe Room TwoはNGUIというフレームワークを使用していることがわかりました。

UIFont.dynamicFontを設定すればダイナミックフォントへ変更可能(日本語表示可能)

NGUIで日本語表示をする方法を探してもUnity Editorでの操作手順やビットマップフォントの情報ばかりでした。頑張ってThe Room Twoへ日本語フォントを追加するしか方法がないのかなぁ…とか思いながらdnSpyでUIFontクラスのコードを眺めているとdynamicFontというFontクラスのプロパティがあるのを発見しました。
ダメもとで下記のようなコードを追加してみたところ日本語が表示されました。


UILabel label = (UILabel)ui;
var fonts = Resources.FindObjectsOfTypeAll();    // The Room Twoの場合、見つかるのは"Arial"一つだけ
label.font.dynamicFont = fonts[0];

しかし、dynamicFontにnullを入れても元のフォントには戻ってくれませんでした。(textに英語を入れても何も表示されない)
下記のようにInstantiateでUIFontをコピーして使用してもダメでした。


// 日本語用フォントへ設定
UILabel label = (UILabel)ui;
UIFont font2 = null;
foreach ( var f in Resources.FindObjectsOfTypeAll<UIFont>() )
{
    if ((label.font.name + "2") == f.name) {
        font2 = f;
        break;
    }
}
if (font2 == null) {
    // 元々使用していたフォント名+"2"という名前でフォントを作成
    var fonts = Resources.FindObjectsOfTypeAll<Font>();
    font2 = Instantiate(label.font);
    font2.name = label.font.name + "2";
    font2.dynamicFont = fonts[0];
}
label.font = font2;

…省略…

// 元のフォントへ戻す
UILabel label = (UILabel)ui;
if (label.font.name.Substring(label.font.name.Length-1, 1) == "2") {
    var name = label.font.name.Substring(0,label.font.name.Length-1);
    foreach ( var f in Resources.FindObjectsOfTypeAll<UIFont>() )
    {
        if (name == f.name) {
            label.font = f;     // コレで元のUIFontに戻しているが表示は空欄(表示なし)になってしまう。
            break;
        }
    }
}
UIFont.dynamicFontを設定する前にUIFont.materialをnullにしておく必要があった

日本語が表示出来ても原文に戻せないと使いづらい。正確にはフォントが戻らないだけで文章は原文へ戻せるんだけど…なんかイヤだ…というわけで、引き続きdnSpyで調査しました。 思いついたことを片っ端から試してみたところ、下記のようにmaterialをnullにしてからdynamicFontを設定すれば元に戻せることがわかりました。


// 日本語用フォントへ設定
UILabel label = (UILabel)ui;
UIFont font2 = null;
foreach ( var f in Resources.FindObjectsOfTypeAll<UIFont>() )
{
    if ((label.font.name + "2") == f.name) {
        font2 = f;
        break;
    }
}
if (font2 == null) {
    // 元々使用していたフォント名+"2"という名前でフォントを作成
    var fonts = Resources.FindObjectsOfTypeAll<Font>();
    font2 = Instantiate(label.font);
    font2.name = label.font.name + "2";
    font2.material = null;		// コレが必要だった!
    font2.dynamicFont = fonts[0];
}
label.font = font2;

…省略…

// 元のフォントへ戻す
UILabel label = (UILabel)ui;
if (label.font.name.Substring(label.font.name.Length-1, 1) == "2") {
    var name = label.font.name.Substring(0,label.font.name.Length-1);
    foreach ( var f in Resources.FindObjectsOfTypeAll<UIFont>() )
    {
        if (name == f.name) {
            label.font = f;
            break;
        }
    }
}

UIFontをInstantiateでコピーしてもmaterialは同じものを参照している。dynamicFontを設定したことで、そちらのUIFontのmaterialへ何らかの変更が入り、元のUIFontにも影響が出てしまった…という事だと思います。

XUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.SetText()を変更して完成

UIFontには一時的にフォントを置き換えるためのreplacementというプロパティが用意されていました。せっかくなのでそれを利用し下記コードとなりました。 追加箇所はXUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.SetText()のui.SetText()直前としました。

BepInEx\plugins\XUnity.AutoTranslator\XUnity.AutoTranslator.Plugin.Core.dll
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<UIFont>() )
                            {
                                if ((label.font.name + "2") == f.name) {
                                    font2 = f;
                                    break;
                                }
                            }
                            if (font2 == null)
                            {
                                var fonts = Resources.FindObjectsOfTypeAll<Font>();
                                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 );
                    …省略…
      }
                    …省略…
   }
}

なお、dnSpyの"Edit Method (C#)..."でXUnity.AutoTranslator.Plugin.Core.AutoTranslationPlugin.SetText()を編集すると下記が原因でCompileエラーとなる場合があります。

読み込んでいるdllが足りない

下記dllの読込は必須です。エラーリスト下にある"Add Assembly Reference (Ctrl+O)"ボタンから足りないdllを追加します。


    BepInEx\plugins\XUnity.AutoTranslator\XUnity.AutoTranslator.Plugin.Core.dll (編集対象)
    BepInEx\core\XUnity.Common.dll
    TheRoomTwo_Data\Managed\Assembly-CSharp.dll
    TheRoomTwo_Data\Managed\UnityEngine.dll

読み込んでいるdllが重複している

dnSpyは足りないdllを自動的に読み込んでくれるようなのですが、System.Core.dllなどが重複してしまいエラーとなる場合があります。その場合はゲーム起動時に読み込まれるであろう方(TheRoomTwo_Data\Managed内のdll)を残し他方を削除します。

Steam版 The Room Two 日本語化(自動翻訳化)

Steam版 The Room 日本語化Modは有志の方々が作成してくださっていますが、The Room Twoの日本語化Modは探しても見つけることができませんでした。

The Roomの日本語化PC ゲーム The Room 日本語化メモ | awgs Foundry
The Room - 意訳とか、Modとか - atwiki(アットウィキ)
Steam コミュニティ :: ガイド :: The Room 日本語化 補完

日本語化ModがなくともUnityで制作されているゲームなのでXUnity.AutoTranslatorで自動翻訳できる…と思ったのですが簡単にはいかなかったのでココにメモを残します。

① BepInEx(x86 v5.4.21)のインストールおよび設定

XUnity.AutoTranslatorにはスタンドアロン(ReiPatcher)版もありますが、基本的にはBepInExプラグインなのでまずはBepInExをインストールします。
しかし、デフォルト設定のままでは真っ黒な画面で止まってしまいました。BepInEx.cfgファイル[Preloader.Entrypoint]のTypeをApplicationからMonoBehaviourへ変更する必要があります。

BepInEx\config\BepInEx.cfg

…省略…

[Preloader.Entrypoint]

## The local filename of the assembly to target.
# Setting type: String
# Default value: UnityEngine.dll
Assembly = UnityEngine.dll

## The name of the type in the entrypoint assembly to search for the entrypoint method.
# Setting type: String
# Default value: Application
Type = MonoBehaviour 

## The name of the method in the specified entrypoint assembly and type to hook and load Chainloader from.
# Setting type: String
# Default value: .cctor
Method = .cctor
② XUnity.AutoTranslator(BepInEx v5.2.0)のインストールおよび設定

BepInEx版のXUnity.AutoTranslatorをインストールします。デフォルトでは日本語→英語になっているので、英語→日本語になるようにAutoTranslatorConfig.iniファイル[General]のLanguage・FromLanguageを変更します。
また、[Service]のEndpointを好みや環境により変更します。(私の環境ではデフォルトのGoogleTranslateV2よりDeepLTranslateの方が安定しています)

BepInEx\config\AutoTranslatorConfig.ini
[Service]
Endpoint=DeepLTranslate
FallbackEndpoint=

[General]
Language=ja
FromLanguage=en

…省略…
③ XUnity.AutoTranslator.Plugin.Core.dllの改造

ゲームを起動するとXUnity.AutoTranslatorにより翻訳されますが日本語が表示できないために文字が消えてしまいます。([Alt]+[T]で英語表示に戻せます) 無理やり日本語を表示させるためにXUnity.AutoTranslator.Plugin.Core.dllを改造します。

パッチ適用方法は同封のreadme.txtをご覧ください。

以上でSteam版 The Room Twoの日本語化(自動翻訳化)が完了です。