Skip to content

Assets ja

Tom_XV edited this page Sep 23, 2026 · 6 revisions

English | 日本語

Assets ライブラリです。ファイルは DragNWash.ModFramework.Assets.dll、名前空間は DragNWash.ModFramework.Assets です。ゲームのフォントでは出せない文字のためのフォントと、Direct3D 12 でもゲームを落とさずにテクスチャやアセットバンドルを読み込むしくみ、それにアセットの道具が入っています。アセットの道具では、何が読み込まれているかを見たり、ゲームのテクスチャを自分のものに差し替えたりできます。

[BepInDependency(GameFonts.Guid, BepInDependency.DependencyFlags.HardDependency)]

タイミングが重要な理由

Drag'n Wash は Unity 6000.3 で動いています。Direct3D 12(Windows の既定)では、テクスチャやフォントアトラスを作ったりアップロードしたりするタイミングが悪いと、D3D12ScratchAllocator でゲームが落ちることがあります(Unity の不具合 UUM-140564)。なので、次のことを守ってください。

  • テクスチャ、バンドル、フォントはプラグインの Awake で読み込み、返ってきたオブジェクトを持ち続けてください
  • それより後で何かするときは、GameInfo.IsDirect3D12 か GameFonts.RuntimeUploadsAreSafe を先に確かめてください。Vulkan(Steam Deck)と Direct3D 11 なら、実行中にアップロードしても問題ありません
  • それでも落ちるプレイヤーには、Steam の起動オプションに -force-d3d11 を付けてもらうのが回避策です

テクスチャとアセットバンドル

private Texture2D _sign;
private AssetBundle _bundle;

private void Awake()
{
    string dir = Path.GetDirectoryName(Info.Location);
    _sign = GameAssets.LoadTexture(Path.Combine(dir, "sign.png"));
    _bundle = GameAssets.LoadBundle(Path.Combine(dir, "mymod.bundle"));
}
メンバー 内容
Texture2D LoadTexture(string path) PNG か JPG を読み込む。同じファイルから読み込み済みならそれを返す。ファイルがない、画像でない場合は null
AssetBundle LoadBundle(string path) バンドルを開く。同じファイルから開き済みならそれを返すので、同じバンドルを同梱した 2 つの Mod でも失敗しない。ファイルがなければ null

どちらも、危ないグラフィックス API の上で遅いタイミングに呼ばれると、ログに警告を出します。

アセットの道具

実験的な機能です。 Assets ライブラリ 1.1.0(2026-09-17 リリース)で入ったものです。

フレームワークが用意するのはゲームのアセットを扱う道具までで、それで何を作るかは、REFramework などと同じく使う人の責任です。ここにあるものがゲームのアセットを配ることはありません。手を加えていないゲームのデータはリポジトリにもリリースにも入れませんし(フレームワーク自身の分は CI が確かめています)、手で作ったものや手を加えたものは コンテンツの方針 に従います(ほかの Mod と一緒に動かす のルール 7)。

覗く

AssetCatalog.Textures()、Materials()、Meshes()、Shaders() で、いま読み込まれているものが一覧になります。名前、サイズ、形式、CPU から読めるかどうか、使っているマテリアルとスプライトの数も付いてきます。その種類の読み込み済みオブジェクトを全部たどるので、毎フレームではなく、ボタンを押したときに呼んでください。

Tool window が入っていれば、Assets タブ(F1。Developer tools がオンのとき)で、読み込まれているテクスチャと Mod が同梱した差し替えを画面で見られます。下の「Assets タブ」を見てください。

Console では assets textures [filter]、assets replacements、assets apply、assets reload が使えます。

差し替える

差し替えたいゲームのテクスチャの名前で、PNG を Mod のフォルダに置きます。

BepInEx/plugins/<あなたの Mod>/assets/textures/<テクスチャ名>.png

テクスチャの名前は、Assets タブに出ている名前です。ライブラリは起動時にこのファイルを全部読み込み(Direct3D 12 でテクスチャのアップロードが安全なのはこのときです)、シーンが読み込まれるたびに、元のテクスチャを使っていたマテリアルのプロパティとスプライトすべてに入れます。スプライトは rect、pivot、pixels-per-unit をそのまま引き継ぐので、PNG は元と同じサイズにしてください。サイズが違うと、rect が画像に合わせて拡大縮小されます。AssetReplacements.ApplyNow() を呼ぶと、そのあとでゲームが作ったマテリアルやスプライトにも同じことをします。

2 つの Mod が同じテクスチャを差し替えたときは、フォルダ名の並びで後ろに来る Mod が勝ち、両方の名前がログと Assets タブに出ます。黙って上書きすることはありません。

メッシュとシェーダー、それに名前以外の条件で対象を選ぶことは、まだできません。ボーン付きのメッシュ(キャラクター)は当面対象外です。

ゲームを動かしたままの読み直し

Assets タブの Reload files(または assets reload)は、差し替えの PNG を全部読み直して、中身が変わったものを入れ替え、当て直します。読み直すのはゲームを起動したときにあったファイルだけなので、あとから足した PNG は次に起動したときに読まれます(そのことはタブが知らせます。1.5.0)。Apply replacements のほうは、読み込み済みのテクスチャにマテリアルとスプライトを向け直すだけです。ライブラリの設定で [Reload] WatchFiles = true(Mods 画面の詳細設定では Watch texture files)にしておくと、ディスク上の PNG が変わったとき、最後の書き込みから 0.5 秒後に自動で読み直します(Direct3D 12 では動きません)。どちらも Developer tools がオンのときだけ使えます。

読み直しはゲームを動かしたままテクスチャをアップロードするので、Direct3D 12 ではゲームが落ちることがあります。ネイティブのクラッシュは捕まえられないので、ライブラリはアップロードの直前に印のファイル(BepInEx/config/<Assets の GUID>.reload-in-progress)を書き、終わったら消します。次の起動でこの印が残っていたら、前回の読み直しでゲームが落ちたということです。そのときはログと Mods 画面にそう出て、[Reload] AllowReload は自分で戻すまでオフになります。Direct3D 12 でこれが 2 回続いたら、ボタンはオフのままになります。起動オプションに -force-d3d11 を付けて作業すれば、こうした心配はありません。

ライブラリが気づける失敗はファイルごとに扱うので、ほかのファイルまで止まることはありません。画像でない PNG や、描画ソフトがまだ保存中のファイル(3 回やり直します)は前のテクスチャのままにして、Assets タブの Replacements に赤い字で、理由つきで並べます。

Assets タブ

(1.5.0)

Tool window が入っていて Developer tools がオンなら、F1 を押して Assets を開きます。一番上の行では Textures (1,234) と Replacements (4) をタブのように切り替えられて、それぞれの数が付き、いま出ているほうには印が付きます。見ておいたほうがいい差し替えがあると、その横に黄色で「2 to check」と出ます。行の残りは絞り込みの欄で、テクスチャの名前で絞り込めて、Replacements のほうでは Mod の名前でも絞り込めます。その下の行には List again、Apply replacements、Reload files があり、指すとヒントの行に何をするボタンかが出ます。窓が狭いとどちらの行も折り返すので、はみ出して見えなくなることはありません。

ボタンの下の状態の行には、最後に押したボタンが何をしたかが出ます。絞り込んでいるときは、何件出ているかが出ます(「Showing 12 of 1,234 textures.」)。その下に残るのは注意だけです。Direct3D 12 では「Direct3D 12: Reload files can crash the game. Apply replacements is always safe.」と出ます。Reload files がオフのときは、その理由と戻し方が出ます。たとえば「Turn AllowReload back on in Options > Mods > Drag'n Wash ModFramework: Assets to try again.」です。Direct3D 11 で読み直しがオンなら、何も出ません。

Textures。 初めてタブを開いたときに、少し「Listing textures...」と出たあと、読み込まれているテクスチャを勝手に一覧にします。Apply replacements や Reload files を押したあとも作り直します。一覧を作ったあとでシーンが変わると、「The scene changed since this list was made.」という黄色い帯が List again のボタンといっしょに出ます。1 行には名前、サイズと形式、使っているマテリアルとスプライトの数、印、それに Inspector が入っていれば Inspect が並びます。印は同じ名前の 2 行を見分けるためのものです。Mod の差し替えには from SignPack(Mod の名前)と出て、それが代わりをしているゲームのテクスチャには original, replaced と出て薄くなります。一覧が狭いとマテリアルとスプライトの数は省かれ、名前の幅が足りなければサイズも省かれます。テクスチャの名前をクリックすると プレビュー が出て、GPU 上のテクスチャがそのまま、市松模様の上に収まる大きさで、サイズ、形式、使っているものといっしょに表示されます。プレビューは一覧の横に、狭い窓では一覧の上に出ます。

Replacements。 ファイル 1 つにつき 1 行で、テクスチャの名前、Mod(言語ごとの画像なら言語も)、それにどうなっているかが出ます。

表示 意味
In 12 places 問題なし。その数のマテリアルとスプライトで使われています。
Not used yet(黄色) まだどこにも入っていません。その名前のテクスチャがそもそも読み込まれているかがヒントの行に出るので、ファイル名の打ち間違いに気づけます。
Not used: CleanSponges wins(黄色) 同じ名前のほかの Mod のファイルが使われています。負けた Mod にも自分の行があるので、その名前で絞り込めば見つかります。
Off(薄い色) Mod が自分でオフにした言語ごとの画像です。
Not reloaded: ...(赤) ファイルを読み直せなかったので、前の画像のままです。続けて理由が出ます。

行を指すと、ヒントの行に説明と、切れて見えなかった部分が出ます。窓が狭いと Mod の列は省かれます。Direct3D 12 で新しい言語の画像が再起動待ちのときは、一覧の上の帯にそう出ます(たとえば Pictures for "ja" apply after a restart (Direct3D 12).)。

ボタンの結果。 結果はふつうの言葉で出ます。Apply replacements なら「Everything was already in place.」か「Put replacements into 5 more places.」です。Reload files なら「Nothing changed on disk.」「Reloaded 2 files.」、問題があったファイルがあればその数が出て、どれだったかが分かるように Replacements に切り替わります。ゲームを起動したときになかった PNG があれば、知らせにその名前が出て、起動したときに読むので使うには再起動してください、と言います。見張っているファイルが勝手に読み直されたとき([Reload] WatchFiles、Direct3D 11)も、「shop_sign.png changed on disk and was reloaded.」のような知らせが出て、一覧が作り直されます。

どちらの一覧もゲームパッドのスティックと十字キーでスクロールできるので、Steam Deck でもトラックパッドやタッチ画面に頼らずに済みます。プレビューの Close と各行の Inspect は大きくなって、押しやすくなりました。

自分でタブを作るなら、窓が狭いと折り返すボタンの並びは ToolWindow.FlowButton(Tool window)で作れます。

言語ごとの画像

実験的な機能です。 フレームワーク 1.4.0 で入ったもので、この先のバージョンで変わったり、無くなったりするかもしれません。

Assets 1.2.0 からは、日本語に訳した看板のように、1 つの言語のときだけ使う画像を Mod に同梱できます。Drag'n Wash Localization の翻訳した画像も、このしくみを使っています。

private void Awake()
{
    GameFonts.SetLanguage("ja");
    string root = Path.Combine(Path.GetDirectoryName(Info.Location), "pictures");
    // pictures/<言語>/textures/<テクスチャ名>.png
    AssetReplacements.AddLanguageFolder(MyMod.Guid, root, "textures");
}
  • AssetReplacements.AddLanguageFolder(guid, root, subfolder) は <root>/<言語>/<subfolder>/*.png を読みます。画像は GameFonts.Language がその言語のときだけ使われ、同じテクスチャの言語を問わない差し替えより優先されます(両方の名前がログに出ます)。Awake から、GameFonts.SetLanguage のあとに呼んでください。
  • 読み込むのは使っている言語の分だけです。言語を変えると、前の言語の画像を戻して新しい言語の画像を読み込みます。Direct3D 12 では新しい画像は再起動まで待ちになり、そのとき使われる言語は AssetReplacements.PendingLanguage で分かります。
  • その言語に画像がないテクスチャは、まずその言語の fallback.txt に書いた言語へ、次に言語を問わない差し替えへ、最後にゲーム自身のものへと戻ります。このファイルは <root>/<言語>/<subfolder>/ に置き、1 行に 1 言語を順番どおりに書きます(# から始まる行はコメントです)。読み込めなかった画像も同じように戻ります。
  • AssetReplacements.SetLanguageFoldersEnabled(guid, on) で、Mod の画像をオフにしたりオンに戻したりできます。切り替えたあとと、言語を変えたあとには AssetReplacements.Changed が呼ばれます。
  • TextureReplacement.Language は画像がどの言語のものかを表し、Assets タブにも出ます。
  • 差し替えは元に戻せます。マテリアルの各プロパティと、スプライトを使っている各部品が前に何を持っていたかを、ライブラリが覚えているからです。

同じバージョンで、操作の登録簿 に読み取りの操作も加わりました。assets.textures.list、assets.materials.list、assets.meshes.list(名前で絞り込み可)、assets.replacements.list(どのゲームのテクスチャを、どの Mod が、どの言語で差し替えているか)、assets.fonts.language です。

予定:取り出しと取り込み

まだ作っていません。平文の形にできる種類は全部、ファイルに書き出して手を加え、Mod から取り込めるようにするつもりです。Mod のリリースに何を入れてよいかはコンテンツの方針どおりで、手で作ったものや手を加えたものは入れてよく、ゲームのデータをそのまま入れることはしません。

種類 書き出し 取り込み(Mod が同梱)
テクスチャ、スプライト PNG。GPU から読み戻すので、ゲームの圧縮テクスチャでも取れる PNG。今と同じ(assets/textures/)
メッシュ(ボーンなし) OBJ OBJ。同じ名前のメッシュを差し替える(assets/meshes/)
マテリアル JSON。シェーダーのプロパティの値とキーワード 変える値だけを書いた JSON(assets/materials/)
シェーダー JSON。プロパティとキーワード(コンパイル済みのシェーダーは含まない) なし
AudioClip WAV。サンプルを読めるクリップだけ(ストリーミングのものは不可) WAV。同じ名前のクリップを差し替える(assets/audio/)
ScriptableObject などシリアライズできるもの シリアライズされるフィールドの JSON 変えるフィールドだけを書いた JSON(assets/data/)
テキストと会話 Drag'n Wash Localization の書き出し その翻訳パック

書き出し先は BepInEx/exports/<ゲームのビルド>/<種類>/ で、NOTICE.txt を添える予定です。書き出しは Export ボタンとコンソールの export <種類> <名前> からで、開発者ツールがオンのときだけにします。取り込むものは起動時に読んで、テクスチャと同じように当てます。手を加えていない書き出しが Mod の zip に入っていたら断る予定です。アニメーションクリップ、フォント、コンパイル済みのシェーダー、ボーン付きのメッシュは対象外です。

コードを書かずにコンポーネントやマテリアルの値を変えるなら、Overrides と Inspector の Export as overrides(Inspector)があります。どちらも 1.4.0 から入った実験的な機能です。

Mod 作者向け

// 差し替えに呼ぶものはありません。ファイルを同梱するだけです。何があるかを見るには:
foreach (TextureInfo t in AssetCatalog.Textures())
    if (t.MaterialUsers > 0) Log($"{t.Name} {t.Width}x{t.Height} {t.Format}");

// ゲームのテクスチャから自分でマテリアルやスプライトを作ったあとに:
AssetReplacements.ApplyNow();

どの言語でも出せるフォント

ゲームのフォントはラテン文字向けです。日本語、中国語、韓国語、ヘブライ語などの文字は、ライブラリがシステムのフォントを読み込んで、TextMeshPro の代替フォントに加えます。

private void Awake()
{
    // その言語で表示しうるテキストを、起動時にすべて準備する
    GameFonts.Prepare("ja", myJapaneseTexts);
    GameFonts.Prepare("zh-Hans", myChineseTexts);

    // 今表示する言語に合わせて、代替フォントの順番を並べる
    GameFonts.SetLanguage("ja");
}
メンバー 内容
void Prepare(string language, IEnumerable<string> texts) テキストが必要とする文字体系ごとにフォントを読み込み、文字を今ラスタライズする。Awake か Update から呼ぶ。準備済みの文字は負担にならない
void SetLanguage(string language) その言語のフォントを先頭にする(中国語のテキストが日本語のフォントではなく中国語のフォントで出るように)。ほかが追加した代替フォントはその後ろに残る。Assets 1.1.1 からは、言語をクラッシュレポートのセッション記録にも書くので、クラッシュレポートのウィンドウがその言語で表示される
string Language 最後に設定した言語
event Action CharactersPrepared 新しい文字やフォントを準備したあとに呼ばれる
string PreparedCharacters これまでに準備したすべての文字。同じテキストを別のフォント(IMGUI)で描くとき用(Tool window 参照)
int CountUnprepared(IEnumerable<string> texts) 準備していない、ASCII 以外の文字の種類の数
void AddFontFolder(string folder) システムのフォントより先に探す、.ttf・.otf・.ttc のフォルダ。ライブラリ自身の fonts フォルダはいつも探す
bool RuntimeUploadsAreSafe Direct3D 12 では false

言語は ja、zh-Hans、zh-Hant、ko、he のようなロケールコードで指定します。

ライブラリの Font atlas point size の設定で、代替フォントの文字をどれくらいくっきり出すかを変えられます。Mods 画面で Show advanced settings をオンにすると出てきて、再起動後に反映されます。

やめてほしいこと

  • TMP_Settings.fallbackFontAssets に自分で追加すること。この一覧はライブラリが全員のために並べています
  • Direct3D 12 で、テクスチャ・フォント・バンドルを「必要になったとき」に読み込むこと

Clone this wiki locally