概要
埋め込みの Scene や Prefab の Image に Addressables な Sprite を使いたいとき、直接参照すると Sprite は二重に保存されてしまいます。
そのため LocalizeSpriteEvent などで動的に Sprite を読み込み表示する必要がありますが、編集中に Sprite が表示されないため不便です。
対象の Sprite を一時的に参照して編集が終わったら外す方法もありますが、手間と外し忘れの恐れがあります。
そこで、Scene や Prefab の編集中だけ Addressables な Sprite を Image にアタッチする Editor 用のコンポーネントを作りました。
Scene, Prefab の保存中に Sprite を取り除き、保存後に Addressables のパスから Sprite を読み込んで実現しています。
コード
使い方
- 対象の Image に
AddressableImageViewerEditor
を追加 - AddressableImageViewerEditor の SpriteRef に Addressables な Sprite を追加
※既に Sprite がアタッチされている Image にAddressableImageViewerEditor
を追加した際は、Sprite を Addressables 化します
プロパティ | 説明 |
---|---|
Image | Sprite を反映する Image です null のとき同じ gameObject に Image があったら自動で追加します |
SpriteRef | 表示する Sprite です Image の SourceImage を変えると、SpriteRef も変わります SpriteRef を変えると、Image の SourceImage も変わります |
ClearSpriteButton | SourceImage と SpriteRef を null にするボタンです |
EditorXXX | 実装の都合で SerializeField にした変数です 編集すると不具合の原因になります |
実装メモ
前提として[ExecuteAlways]
を有効にしています。
編集中だけアタッチする方法
PrefabStage.prefabSaving, EditorSceneManager.sceneSaving でアタッチを外し、PrefabStage.prefabSaved, EditorSceneManager.sceneSaved で再度アタッチしています。
Scene, Prefab の編集開始時は、Update() で editorIsNotReflected フラグを利用してアタッチしています。
Start() ではなく Update() を使う理由
Scene 上の GameObject から Prefab を作成すると、オリジナルの GameObject は消えて Prefab の Instance が生成されます。その Instance は Start() の後に Prefab の値を反映するようなので、Update() でアタッチしています。
保存中に OnValidate() を止める方法
OnValidate() は PrefabStage.prefabSaving と PrefabStage.prefabSaved の間にも呼ばれます。
つまり、prefabSaving 中に値を変更しても OnValidate() によって値が変わる恐れがあります。
そこで、prefabSaving で editorIsNotReflected フラグを有効に、prefabSaved でフラグを無効にして OnValidate() にフラグを使った早期リターンを作ることで値が変わらないようにしました。
その他
Prefab Variant による ImageSource の override はPrefabUtility.RevertPropertyOverride()
で対処しています。
Prefab の生成直前に ImageSource を空にする事は難しいので、AssetPostprocessor.OnPostprocessAllAssets()
で生成された Prefab を編集して ImageSource を空にしています。これにより Prefab の Import が僅かに遅くなる恐れがあります。
本当に ImageSource が空になっているか怪しい際は Scene, Prefab をテキストエディタで確認してください。不具合がありましたらコメントをいただけると助かります。