Last active
January 8, 2020 06:51
-
-
Save FreyaHolmer/80a83d0fe24ba6e781e4 to your computer and use it in GitHub Desktop.
ScriptableObject asset spawner for Unity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Adds a menu item for easy creation of your ScriptableObject types | |
// Usage: Right click in project view -> Create -> ScriptableObject... -> Select your type | |
// It will land in the root of your assets folder with the same name as your class | |
// Freya Holmér - [email protected] | |
using UnityEngine; | |
using UnityEditor; | |
using System.Reflection; | |
using System.Linq; | |
using System.IO; | |
public class ScriptableObjectSpawner : EditorWindow { | |
// Config | |
const bool CLOSE_AFTER_SPAWNING = true; | |
const bool SELECT_AFTER_SPAWN = true; | |
// Variables | |
string[] m_TypeNames; | |
string[] m_AssemblyNames; | |
System.Type[] m_Types; | |
GUIStyle m_LeftAlignedButtonStyle; | |
Vector2 m_ScrollViewPos; | |
// Window spawning | |
[MenuItem( "Assets/Create/ScriptableObject..." )] | |
static void Init() { | |
ScriptableObjectSpawner window = (ScriptableObjectSpawner)EditorWindow.GetWindow( typeof( ScriptableObjectSpawner ), true ); | |
window.title = "Select a type..."; | |
window.Center(); | |
} | |
// Center on screen | |
void Center(){ | |
Rect scPos = this.position; | |
scPos.center = new Vector2(Screen.currentResolution.width, Screen.currentResolution.height) / 2; | |
this.position = scPos; | |
} | |
// Interface | |
void OnGUI() { | |
if( m_TypeNames == null || m_Types == null || m_LeftAlignedButtonStyle == null ) | |
Reload(); | |
m_ScrollViewPos = EditorGUILayout.BeginScrollView( m_ScrollViewPos ); | |
float halfWidth = ( Screen.width / 2 ) - 13; | |
for( int i = 0; i < m_Types.Length; i++ ) { | |
GUILayout.BeginHorizontal(); | |
if( GUILayout.Button( m_TypeNames[i], m_LeftAlignedButtonStyle, GUILayout.Width( halfWidth ) ) ) { | |
ScriptableObject so = ScriptableObject.CreateInstance( m_Types[i] ); | |
AssetDatabase.CreateAsset( so, GetUniqueAssetPath( m_Types[i] ) ); | |
if( SELECT_AFTER_SPAWN ) | |
Selection.objects = new Object[] { so }; | |
EditorGUIUtility.PingObject( so ); | |
if( CLOSE_AFTER_SPAWNING ) | |
Close(); | |
} | |
GUILayout.Label( m_AssemblyNames[i], GUILayout.Width( halfWidth ) ); | |
GUILayout.EndHorizontal(); | |
} | |
EditorGUILayout.EndScrollView(); | |
} | |
// Reload data and recache arrays | |
void Reload() { | |
Assembly[] asms = System.AppDomain.CurrentDomain.GetAssemblies().Where( x => x.FullName.StartsWith( "Assembly-CSharp" ) ).ToArray(); | |
m_Types = asms.SelectMany( x => x.GetTypes().Where( type => type.IsSubclassOf( typeof( ScriptableObject ) ) && !type.IsSubclassOf( typeof( Editor ) ) && !type.IsSubclassOf( typeof( EditorWindow ) ) ) ).OrderBy( x => x.Name ).ToArray(); | |
m_TypeNames = m_Types.Select( x => x.Name ).ToArray(); | |
m_AssemblyNames = m_Types.Select( x => x.Assembly.FullName.Split( ',' )[0] ).ToArray(); | |
m_LeftAlignedButtonStyle = new GUIStyle( GUI.skin.button ); | |
m_LeftAlignedButtonStyle.alignment = TextAnchor.MiddleLeft; | |
} | |
// Used to make sure names are incremental, eg. MyObject, MyObject_2, MyObject_3 | |
string GetUniqueAssetPath( System.Type type ) { | |
string typeName = type.Name; | |
string folder = GetAssetFolder(); | |
string path = folder + typeName + ".asset"; | |
if( AssetDatabase.LoadAssetAtPath( path, type ) == null ) | |
return path; | |
int i = 2; | |
do { | |
path = folder + typeName + "_" + i + ".asset"; | |
i++; | |
} while( AssetDatabase.LoadAssetAtPath( path, type ) != null ); | |
return path; | |
} | |
// Get the folder to create the asset in | |
string GetAssetFolder(){ | |
Object[] selection = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets); | |
if( selection != null && selection.Length > 0 ){ // If any assets are selected | |
for(int i=0;i<selection.Length;i++){ // Search for a folder | |
string path = AssetDatabase.GetAssetPath(selection[i]); | |
if(Directory.Exists(Application.dataPath.Substring(0,Application.dataPath.Length-6) + path)){ | |
return path + "/"; | |
} | |
} | |
return Path.GetDirectoryName( AssetDatabase.GetAssetPath(selection[0])) + "/"; // If no folder was found, grab the first object's directory | |
} | |
return "Assets/"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment