- Home /
CustomEditor for an asset group -- is it possible?
Ok, this is a hard one. I've been searching the web for an answer for two days and haven't found anything. Here we go...
Suppose I have a group of assets created like this:
var customScript1 = ScriptableObject.CreateInstance<CustomScript1>();
var customScript2 = ScriptableObject.CreateInstance<CustomScript2>();
AssetDatabase.CreateAsset(customScript1, "Assets/");
AssetDatabase.AddObjectToAsset(customScript2, customScript1);
Now, the produced (combined) asset should be akin to this (as seen in the project view):
- root (asset?)
+ custom script 1
+ custom script 2
Can I attach a CustomEditor to the root to show in the Inspector?
What do you want to show in the inspector? Do you want it to look like the inspector for a GameObject with the different Components etc. ?
A few serialized fields from one of the scripts. Why? Do you know of a way to attach a custom editor to the root?
This is very useful! also look at Unite 2014 - The Hack Spectrum: Tips, Tricks and Hacks for Unity.
Thanks. Note that it changed slightly in Unity 5. It's no longer [CustomEditor(typeof(Object))]
, it's [CustomEditor(typeof(DefaultAsset))]
ins$$anonymous$$d.
Answer by Jamora · Aug 14, 2013 at 09:46 PM
It is possible to show custom editors for child assets in a combined asset like what you describe. My script has a few assumptions:
You need a custom editor script for each (my script assumes it is classname+"Editor").
You need to have your combined asset beginning with "custom".
If you want to make them look like what Unity does with GameObjects, you'll need at least the default inspector titlebar.
This is basically what I came up with:
using UnityEngine;
using UnityEditor;
using System.Collections;
[CustomEditor(typeof(Object))]
public class testEditor : Editor {
Object[] targetArray;
void OnEnable(){
if(targetArray == null)
targetArray = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(target));
}
public override void OnInspectorGUI(){
/*this can be left out but will cause this to be urn on everything you select in the hierarchy.
* Right now it only runs on things that begin with custom.
*/
if(target.name.StartsWith("custom")){
foreach(ScriptableObject obj in targetArray){
//Show the custom editors for all the ScriptableObjects that are within the target
CreateEditor(obj,System.Type.GetType(obj.GetType().ToString()+"Editor")).OnInspectorGUI();
}
}
}
}
I see. So basically you override the Inspector view for every object, which doesn't have a more specific CustomEditor defined. And then filter the asset in question by name. It's an interesting approach. I'll think on it. Thank you.
Just a small correction to your code though:
if(target.name.StartsWith("custom")){
...
}
else {
DrawDefaultInspector();
}
Thanks a lot! You were very helpful.
Turns out [CustomEditor(typeof(UnityEngine.Object))]
applies only to general assets such as combined assets, folders, scenes, and unrecognized custom assets, and nothing else (not even ScriptableObjects, even with CustomEditor(typeof(UnityEngine.Object), true)
). So I could leave out the na$$anonymous$$g mumbo-jumbo and use this code for all unrecognized custom assets (which shows better info than a blank page anyway):
[CustomEditor(typeof(UnityEngine.Object))]
public class ObjectInspector : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (combinedAssets != null) {
int i = 0;
foreach (var asset in combinedAssets) {
if (asset != target) {
foldStates[i] = EditorGUILayout.InspectorTitlebar(foldStates[i], asset);
if (foldStates[i]) {
var editor = Editor.CreateEditor(asset);
editor.OnInspectorGUI();
}
}
++i;
}
}
}
protected virtual void OnEnable()
{
var assetPath = AssetDatabase.GetAssetPath(target);
if ((assetPath != null) && (assetPath.EndsWith(".asset"))) {
combinedAssets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
if (combinedAssets != null) {
foldStates = new List<bool>(combinedAssets.Length);
for (int i = 0; i < combinedAssets.Length; ++i) {
foldStates.Add(true);
}
}
}
}
protected virtual void OnDisable()
{
combinedAssets = null;
foldStates = null;
}
Object[] combinedAssets;
List<bool> foldStates;
}
It appears that a default editor always exists for any asset.
Note that it changed slightly in Unity 5. It's no longer [CustomEditor(typeof(Object))]
, it's [CustomEditor(typeof(DefaultAsset))]
ins$$anonymous$$d.
I couldn't get the custom editor firing on the parent asset no matter what I tried, either Object or DefaultAsset. Is there something I'm missing? I'm trying to get any kind of life from my custom editor when selecting the group asset's parent but nada.