環境
Unity 2019.2.17f1
Addressable 1.5
Odin Inspector 2.1.8 (有料プラグイン)
AssetReferenceって何を参照しているのか分かりにくい。。。
名前を設定している場合はまだ分かりやすいですが、フォルダを指定している場合フルパスが表示されるのでかなり分かり辛いです。それを有料プラグインのOdinを使って解決してみようと思います。
まずは Before / After
Before...
After !!!!
だいぶ分かりやすくなりましたね。
Prefab名をクリックするとProject内のPrefabをハイライトしてくれます。
そしてグループでのフィルタリングにも対応しました。
Code
OdinWithAddressableAssetReference.cs
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using Sirenix.OdinInspector;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
#endif
[CreateAssetMenu(menuName = "Sample/OdinWithAddressableAssetReference")]
public sealed class OdinWithAddressableAssetReference : ScriptableObject
{
[SerializeField, HideInInspector] AssetReferenceGameObject references;
public AssetReferenceGameObject References => references;
#region Inspector
#if UNITY_EDITOR
#pragma warning disable 0649
[SerializeField, ValueDropdown("ReferenceDropDownEditorOnly"), OnValueChanged("ReferenceValueChangedEditorOnly"), LabelText("References")] string referenceGuidEditorOnly;
[ShowInInspector, ReadOnly, InlineEditor(InlineEditorModes.LargePreview), ShowIf("ReferencePreviewShowIfEditorOnly")] GameObject PreviewOnEditor;
[SerializeField, ValueDropdown("AssetGroupDropDownEditorOnly", IsUniqueList = true), LabelText("Addressable Group Filter")] string[] targetAssetGroupGuidsEditorOnly;
#pragma warning restore 0649
IEnumerable ReferenceDropDownEditorOnly()
{
return GetAllAssetEntrys(targetAssetGroupGuidsEditorOnly)
.Select(x => new ValueDropdownItem(x.AssetPath, x.guid));
}
IEnumerable AssetGroupDropDownEditorOnly()
{
return GetAllAssetGroups()
.Select(x => new ValueDropdownItem(x.Name, x.Guid));
}
void ReferenceValueChangedEditorOnly(string guid)
{
var entrys = GetAllAssetEntrys(targetAssetGroupGuidsEditorOnly);
var item = entrys.FirstOrDefault(x => x.guid == guid);
if (item != default)
{
references = new AssetReferenceGameObject(item.guid);
UpdatePreviewAssetEditorOnly();
}
}
bool ReferencePreviewShowIfEditorOnly()
{
if(PreviewOnEditor == default)
{
UpdatePreviewAssetEditorOnly();
}
return PreviewOnEditor != default;
}
void UpdatePreviewAssetEditorOnly()
{
PreviewOnEditor = default;
if(references.RuntimeKeyIsValid())
{
PreviewOnEditor = LoadAsset<GameObject>(references);
}
}
/// <summary>
/// アセットの取得
/// </summary>
/// <returns>The asset.</returns>
/// <param name="reference">Reference.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static T LoadAsset<T>(AssetReference reference) where T : Object
{
return reference.RuntimeKeyIsValid()
? AssetDatabase.LoadAssetAtPath<T>(AssetDatabase.GUIDToAssetPath(reference.AssetGUID))
: default;
}
/// <summary>
/// グループ一覧を取得
/// </summary>
/// <returns>The asset groups.</returns>
public static List<AddressableAssetGroup> GetAllAssetGroups()
{
var setting = AddressableAssetSettingsDefaultObject.GetSettings(false);
var gropus = new List<AddressableAssetGroup>();
if (setting != default)
{
gropus = setting.groups;
}
return gropus;
}
/// <summary>
/// 全エントリーを取得
/// </summary>
/// <returns>The asset entrys editor only.</returns>
/// <param name="groupFilterGuids">Group filter.</param>
public static List<AddressableAssetEntry> GetAllAssetEntrys(string[] groupFilterGuids = null)
{
var setting = AddressableAssetSettingsDefaultObject.GetSettings(false);
var entrys = new List<AddressableAssetEntry>();
if (setting != default)
{
foreach (var group in setting.groups)
{
if (groupFilterGuids != null
&& groupFilterGuids.Length > 0
&& !groupFilterGuids.Any(guid => guid == group.Guid))
{
continue;
}
var _entrys = new List<AddressableAssetEntry>();
group.GatherAllAssets(_entrys, false, true, false);
entrys.AddRange(_entrys);
}
}
return entrys;
}
#endif
#endregion
}
実装のポイント
AddressableAssetSettingsの取得方法が変わりました
OdinWithAddressableAssetReference.cs
var setting = AddressableAssetSettingsDefaultObject.GetSettings(false);
プレビュー用GameObjectをシリアライズされないようにする
プレビューを表示するためのGameObjectがシリアライズされないようにprivateでShowInInspectorアトリビュートを使用しています。
publicにしたい場合は、[System.NonSerialized]を追加。
更に、プレビューは参照だけで使用されることが無いので#pragma warningでCS0649警告が表示されないようにしています。
OdinWithAddressableAssetReference.cs
[ShowInInspector, (略)] GameObject PreviewOnEditor;
OdinでAddressableは非対応なのでGuidを保存する
ドロップダウンは実はテキストです(string referenceGuidEditorOnly)。 表示するリストを生成する際(ReferenceDropDownEditorOnly())、表示用のアセットパスと保存用のGuidをOdinのValueDropdownItemに代入しています。 そして、Guidに変更があった場合(ReferenceValueChangedEditorOnly(string guid))でプレビューを更新する仕様です。OdinWithAddressableAssetReference.cs
[SerializeField, ValueDropdown("ReferenceDropDownEditorOnly"), OnValueChanged("ReferenceValueChangedEditorOnly"), LabelText("References")] string referenceGuidEditorOnly;
IEnumerable ReferenceDropDownEditorOnly()
{
return GetAllAssetEntrys(targetAssetGroupGuidsEditorOnly)
.Select(x => new ValueDropdownItem(x.AssetPath, x.guid));
}
void ReferenceValueChangedEditorOnly(string guid)
{
var entrys = GetAllAssetEntrys(targetAssetGroupGuidsEditorOnly);
var item = entrys.FirstOrDefault(x => x.guid == guid);
if (item != default)
{
references = new AssetReferenceGameObject(item.guid);
UpdatePreviewAssetEditorOnly();
}
}
/// <summary>
/// 全エントリーを取得
/// </summary>
/// <returns>The asset entrys editor only.</returns>
/// <param name="groupFilterGuids">Group filter.</param>
public static List<AddressableAssetEntry> GetAllAssetEntrys(string[] groupFilterGuids = null)
{
var setting = AddressableAssetSettingsDefaultObject.GetSettings(false);
var entrys = new List<AddressableAssetEntry>();
if (setting != default)
{
foreach (var group in setting.groups)
{
if (groupFilterGuids != null
&& groupFilterGuids.Length > 0
&& !groupFilterGuids.Any(guid => guid == group.Guid))
{
continue;
}
var _entrys = new List<AddressableAssetEntry>();
group.GatherAllAssets(_entrys, false, true, false);
entrys.AddRange(_entrys);
}
}
return entrys;
}