Supermarket Simulator レジ増殖バグ(?)再現手順
Supermarket Simulator (v0.1.2.4)で遊んでいると、いつの間にかレジが二重になっていてチェックアウトが出来ない…というバグ(?)が発生しました。
また急に発生したらイヤだなぁ…と思い、いろいろ試したところ再現手順がわかりましたので以下に記します。
このバグ(?)が発生しないようにするポイントは
設置されているレジが無い状態でゲームを終了しない
ことです。
① レジを [C]詰める でダンボールにして置いておく


② [ESC]で メニューに戻る でメインメニューに戻って 続ける で再開


レジが増えている(ダンボールのレジはそのままで、設置されたレジが現れる)
③ 増えたレジを [C]詰める でダンボールにして置いておく


④ ①でダンボールに詰めたレジを開いて配置


⑤ [ESC]で メニューに戻る でメインメニューに戻って 続ける で再開


なぜか配置していたレジが二重になっている
②までの動きは、設置されたレジが無くならないように…という処理なのかな?と思いますが③以降は…まぁEarly Accessですしね。
冒頭でも記しましたが
設置されているレジが無い状態でゲームを終了しない
ようにご注意ください。
XUnity.AutoTranslator による日本語化(自動翻訳化)の手順
(忘れる程時間が経っていると各種ツールのバージョンが上がっていて、これまでのやり方が通じなくなっていた…なんて事は良くあるので無駄になるかも知れませんが…)
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が使用できています。ゲーム画面に何らかの変化(日本語表示された/文字が消えた)が起きているはずなので前述に従ってください。


単に今まで表示された画面にテキストがなかった(表示された英語は文字情報ではなく画像だった)だけかも知れないので、オプションメニューへ変えてみたりゲーム本編の画面まで進めて見たりして、ゲーム中で様々な画面を表示させてみます。
それでも"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を閉じます。
【詳細②】Steam版 The Room 4: Old Sins 日本語化(自動翻訳化)

せっかくなので、その事について まとめておきたいと思います。
対象フォントの選定
| 名前 | コンテナ |
|---|---|
| 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 |
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 ---");

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 ---
使用する日本語フォントの選定
Sans系というのはSans-Serifのことで、セリフ(飾り)が無いって事らしい。ArialやMSゴシックと同類(?)
Antique(アンティーク)は文字通りアンティーク調(?)。『Caslon Antique』で検索すると若干かすれたような見た目のフォントも見つかった。Garamondと同類(?)
CaslonAntiqueが縦長な文字(長方形)なのに対してこちらは正方形に近い感じ。Centuryに似ている??
| TheRoom4のフォント | 日本語フォント |
|---|---|
| LiberationSans SDF | Noto Sans Japanese (Regular) |
| CaslonAntique SDF | BIZ UDMincho (Regular) |
| TheRoom SDF | Noto Serif Japanese (Regular) |
TheRoom4からのエクスポート
| ファイル名 | # | オブジェクト名 |
|---|---|---|
| resources.assets | 860 | LiberationSans SDF Atlas |
| resources.assets | 865 | CaslonAntique SDF Atlas |
| sharedassets0.assets | 6 | TheRoom SDF Atlas |
| ファイル名 | # | オブジェクト名 |
|---|---|---|
| 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 |


PointSize,Padding等の確認
| Name | PointSize | Padding | AtlasWidth | AtlasHeight |
|---|---|---|---|---|
| CaslonAntique SDF | 44 | 5 | 512 | 512 |
| LiberationSans SDF | 86 | 9 | 1024 | 1024 |
| TheRoom SDF | 32 | 5 | 512 | 512 |
| 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 | 2019.4.5f1 |
| TextMeshPro | 1.0.23 |
| 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 | ☑ |
| 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 | ☑ |
| Font Source | NotoSerifJP-Regular.otf |
|---|---|
| Font Size | Custom Size : 32 |
| 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 | ☑ |

自作ゲーム(?)からのエクスポートおよびリネーム
| オブジェクト名 | エクスポートされたファイル名 ※ | リネーム後のファイル名 |
|---|---|---|
| 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の書き換え
参考記事と設定ファイルに同封されていたメモをもとにTheRoom4(TextMeshPro v1.0.23)での変更箇所は下記としました。(下記項目をTheRoom4の値で上書きしていく)
- ① 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
- ① 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
- 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へのインポート
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.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 |
日本語フォント化完了

翻訳サービスを利用するならXUnity.AutoTranslatorが便利で、XUnity.AutoTranslatorを使用するならAssetBundleでの日本語フォント化の方が導入しやすい…と思い、こちらは作っただけでほとんど使用して(遊んで)いません。
ただせっかくなので記事を書かせていただきました。どなたかの そして なにかの参考になれば幸いです。
Steam版 The Room 4: Old Sins 日本語化(自動翻訳化)

① BepInEx(UnityIL2CPP x64 v6.0.0pre.1)のインストール
② XUnity.AutoTranslator(BepInEx IL2CPP v5.2.0)のインストールおよび設定
[Service]
Endpoint=DeepLTranslate
FallbackEndpoint=
[General]
Language=ja
FromLanguage=en
…省略…
③ 日本語表示用フォントの適用
…省略…
[Behaviour]
…省略…
OverrideFontTextMeshPro=bizudmincho_TheRoom4
FallbackFontTextMeshPro=
…省略…
以上でSteam版 The Room 4: Old Sinsの日本語化(自動翻訳化)は完了です。 ゲームを起動するとEndpointで指定されたサービスを用いて翻訳され日本語が表示されるはずです。

余談: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
なお、この2つの設定項目についてXUnity.AutoTranslatorのドキュメントでは下記のように記載されています。(訳:DeepL翻訳)
- ① FallbackFontTextMeshProのみにフォントを指定して試してみる。
- ② ①で不都合が生じたらOverrideFontTextMeshProのみにフォントを指定する。
(FallbackFontTextMeshProを空欄に戻すのを忘れないこと)
【詳細】Steam版 The Room 4: Old Sins 日本語化(自動翻訳化)
The Room Two, Three と日本語フォントへ強制変更するコードをXUnity.AutoTranslatorへ追加するというアヤしい方法ながらも何とか日本語化(自動翻訳化)に成功しました。 そしてThe Room 4: Old Sinsです。最新作なのできっとTextMeshProが使われていて、難なくXUnity.AutoTranslatorで翻訳できるんだろうなぁ…と思っていたのですがハマりました。最終的にはOverrideFontTextMeshProで指定できるフォントを自作し日本語化(自動翻訳化)は出来たのですが、その過程でいろいろと試したことや分かったことがありますのでココに残したいと思います。
分かった事のまとめ
以降、ほぼ時系列で試したことや分かったことを記載していきます。TheRoom4は『OverrideFontTextMeshPro = arialuni_sdf_u2019』が効かない
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]で制作されている。
日本語へ翻訳されたが日本語が表示できるフォントではないので文字のない(もう見慣れた)メインメニューが表示されます。 ここで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
[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] 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
- "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以前)
TextMeshProのドキュメントを見るとTMP_FontAssetにCreateFontAssetというメソッドを発見。これが使えないか試そうとBepInEx\unhollowed\TextMeshPro.dllを見るとCreateFontAssetというメソッドがない。
il2cppだから見れないだけで本当はあるのかな?と思いXuaLogger.AutoTranslatorの既存コードをマネてメソッド取得を試みるも失敗。GetCharactersなど見えているメソッドは取得できるので追加したコードにミスがあるわけではなく、見えない=本当にない という事のようでした。ちなみにCreateFontAssetがないTextMeshProがあり得るのかバージョンを遡るとv1.3以前ならCreateFontAssetがないようでした。
CreateFontAsset以外にコードでUnityEngine.FontからTMP_FontAssetを作成する方法が見つからず(思いつかず)また行き詰ってしまいました。 そのため大変そうですが下記記事を参考にゲームのリソース(Assets)を書き換えてフォントを日本語化させる方法を試してみる事にしました。 (※こちらの方法でもフォントの日本語化に成功しています。せっかくなので後日記事にするかも知れません。)
PointSize, Paddingという数値はありますがm_fontInfoというセクション内だけで他に存在しません。またm_CreationSettingsに似た名前としてfontCreationSettingsというセクションがあります。
ドキュメントを確認するとv1.2以前はm_CreationSettingsではなくfontCreationSettingsだったようです。
しかし最も古いv1.0.26のドキュメントにも記載はありません。
v1.0.25 : なし (FormerlySerializedAsの記載あり)
v1.0.23 : あり
v1.0.21 : あり
ちなみにTheRoom4が使用しているUnityはv2019.4.5f1で、このバージョンのUnityと同時にインストールされるTextMeshProはv2.0.1でした。
AssetBundleのTMP_FontAssetにあるm_AssemblyNameはゲーム内と同じにする必要がある
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
結局、ゲームのAssetsを書き換えてフォントを日本語化させる方法がうまくいったので、OverrideFontTextMeshProが利用できなかったのは謎のまま終わりにしようと思ったのですが、ブログを記載するためにメモを整理していたら下記を確認していないことに気づきました。
- ① ゲームのAssets内に"TMP_FontAsset"という名前のオブジェクトが存在するか?(AssetBundleにはあった)
- ② もしゲーム内にも存在した場合、AssetBundle内の内容とどこが違うのか?
- ③ もしゲーム内にも存在した場合、AssetBundle内のTMP_FontAssetをゲーム内のTMP_FontAssetで上書きすればOverrideFontTextMeshProで使用できないか?






[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_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をセットアップしているような気がします。)
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を変更します。
[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()直前としました。
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)を残し他方を削除します。
