Skip to content

Instantly share code, notes, and snippets.

@FreyaHolmer
Last active January 8, 2020 06:51
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save FreyaHolmer/80a83d0fe24ba6e781e4 to your computer and use it in GitHub Desktop.
Save FreyaHolmer/80a83d0fe24ba6e781e4 to your computer and use it in GitHub Desktop.
ScriptableObject asset spawner for Unity
// 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 - webmaster@acegikmo.com
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