Scene Management チームからプレハブの最新情報を共有するのは久しぶりです。この数回のリリースで、皆様から報告された多くのバグを修正し(バグをご報告してくださった皆さん、ありがとうございます!)、プレハブシステムにいくつかの改良を加えました。現在 Unity 2022.2 ベータ版で提供されている改善点をそれぞれ見ながら、これらのアップデートがどのような恩恵をもたらすかを見てみましょう。
シーン内または他のプレハブにネストされて存在するプレハブのインスタンスのプレハブアセットの置換が可能になりました。この機能は、プレハブのインスタンスのシーン内での位置、回転、スケールを維持しながら、新しいプレハブアセットからコンテンツをマージし、名前ベースのマッチング(デフォルト)によってできるだけ多くのオーバーライドと参照を保持します。さらに具体的に言うと、以下の通りです。
この機能は UI だけでなく、私たちが構築したほとんどの機能と同様に、オブジェクトのマッチング方法やオーバーライドの扱い方を管理できる API を備えています。PrefabUtility.ReplacePrefabAssetOfPrefabInstance および PrefabUtility.ConvertToPrefabInstance の説明をご覧ください。
最も要望の多かった改善点の 1 つが、追加したゲームオブジェクトやコンポーネントを並び替えられるようにする機能です。「追加したゲームオブジェクトやコンポーネント」とは、プレハブのインスタンスの一部ではありませんが、シーン内またはバリアントやネスト状のプレハブの中に追加されたゲームオブジェクトやコンポーネントのことです。Unity 2022.1 からは、追加したゲームオブジェクトやプレハブのインスタンスに属するゲームオブジェクトをドラッグアンドドロップで並び替えられるようになりました。この機能を準備するために、Undo システムの大幅なリファクタリングが必要でした。
エディタースクリプトから追加したゲームオブジェクトを並び替えたい場合は、追加したゲームオブジェクトのトランスフォームの兄弟オブジェクトのインデックスを設定するだけでそれができます。インスペクターに追加されたコンポーネントを並べ替える機能は、Unity 2022.2 で提供されます。コンポーネントを並べ替えるための公開 API はありません。
ゲームオブジェクトとコンポーネントの間で完全な機能パリティを実現するために必要な最後のピースは、オーバーライドとしてプレハブのインスタンスからゲームオブジェクトを削除する機能でした。Unity 2022.2 でオプション機能として提供されているゲームオブジェクトをオーバーライドとして削除する機能により、一度ゲームオブジェクトを削除しても、プレハブアセットから巻き戻す、あるいはプレハブアセットに適用するための通常のワークフローが期待通りに動作するようになりました。
エディタースクリプトに関しては、Object.DestroyImmediate を使ってプレハブのインスタンスオブジェクトを破棄し、シーンファイルに格納されているオーバーライドとしてその破棄操作を記録します。
ユーザーは特定のプレハブアセットのバリアントの継承ツリーがどのようになっているかを調べることがしばしばあります。Unity 2022.2 では、インスペクターに Prefab Family ポップアップが追加されました。ポップアップの内容は、プロジェクトブラウザーで選択したプレハブアセットに依存します。プレハブアセットを選択して Prefab Family ポップアップを開くと、エディターにその時選んでいるプレハブの祖先と直系の子がすべてリストアップされます。
継承ツリーに関する問い合わせ以外に、プロパティがスクリプトから削除されているためにシーンに保存されているがアクセスされていない未使用のオーバーライドを取り除く方法についてもユーザーからよく問い合わせがありました。最悪の場合、このようなプロパティによって参照されているが故に、ストレージデバイスやメモリのスペースを占有するものの、決して使用されることのないアセットが最終ビルドに取り込まれることもあります。
そこで、以下のようなオーバーライドについては未使用のフラグが立つようになりました。
ヒエラルキーで 1 つ以上のプレハブのインスタンスを選択して Overrides ドロップダウンを開くと、未使用のオーバーライドがあるかどうかがエディターに表示されるようになりました。その後、新しく追加された Unused Overrides ドロップダウンを使用して、シーンからそれらのオーバーライドを削除することができます。
さらに、ヒエラルキーのシーンのコンテキストメニューや、任意に選択されたプレハブのインスタンスに対してはコンテキストメニューから、シーン内の未使用のオーバーライドをすべて削除することが可能です。
未使用のオーバーライドが自動的に削除されることはありません。これは結局、そのオーバーライドが存在している理由を推量できないからです。スクリプトからプロパティを削除したり、アセットを削除しても、その削除の操作を取り消したり、オーバーライドを復旧させたりする場合があるため、未使用のオーバーライドが自動的に削除されることはありません。
「『Apply All』を押したのに、プレハブのインスタンスにオーバーライドが残っているのはなぜだろう」と思った方がいらっしゃるかもしれません。その疑問に対する答えは、これらのオーバーライドはプレハブアセットに適用できないから、というものになります。このようなオーバーライドは、プレハブアセットから参照できないシーン内の他のオブジェクトの参照となっているのが一般的です。通常適用されないオーバーライドは、インスペクターで暗い青色のバーでハイライトされるようになりました。これらは適用することはできず、元に戻すことだけが可能です。
プレハブモードを開いたときのデフォルトの動作を、In Context ではなく、In Isolation に変更できるようになりました。エディターの環境設定 の General > Default Prefab Mode で、この変更を行うことができます。
Unity 2022.2 では、プレハブモードを終了する際に Undo が 1 回分記録されるようになりました。このため、プレハブモードを終了した後に Undo を行うと、プレハブに加えられたすべての変更が元に戻ってしまいます。
リリースを重ねるうち、シーンの読み込み(およびプレハブモードでのプレハブの読み込み)中のエラー処理とレポート生成が大幅に改善され、エラーがどのプレハブに関連しているか、または見つからないプレハブの GUID を表示するようになりました。実際、シーンの読み込み中にプレハブのアセットが見つからない場合の処理方法は、以前よりも安全で安定したものになっています。
エラー処理をさらに改善し、プロジェクトに不良データを持ち込まないようにするため、Broken Prefab アセットタイプを追加しました。これは、修正できないエラーが発生したときにプレハブインポーターによって生成されるものです。
最も一般的なケースは、プレハブバリアントが、(おそらくは削除されたために)親のプレハブを失った場合です。この場合、意味のあるプレハブバリアントを生成できないので、代わりに Broken Prefab アセットが作成されます。この新しいアセットをプロジェクトブラウザーで選択すると、インスペクターで何が問題なのかの情報が表示されます。プレハブの親が見つからない場合であれば、見つからないプレハブの GUID が表示されます。また、プレハブバリアントのチェーンが壊れている場合、インスペクターでチェーンをさかのぼって、親が見つからないバリアントを見つけることができます。
接続が解除されたプレハブインスタンスという概念は Unity 2022.1 の時点で存在しなくなりました。接続が解除されたインスタンスの読み込みはまだサポートしていますが、シーン読み込み中にエディターが接続が解除されたプレハブのインスタンスを見つけると、接続が解除されたインスタンスはすべてのプレハブ情報を取り除かれて通常のゲームオブジェクトになります。
言及した通り、これまで皆さんからご報告いただいた一連のバグを修正しました。その中には、もともとのプレハブシステムに由来するものもありますが、プレハブを改良したことで初めて明らかになったものも多くあります。
いま、私たちは、最新のプレハブシステムの安定性を皆さんに享受していただけると確信しています。これを使って、皆さんが作業がスムーズで効率的になったと感じていただければ幸いです。
その他、プレハブに関するご質問やコメントがある方は、フォーラムでぜひお聞かせください。