Editorscript: Generate enum from string[]
Asked Answered
P

4

0

I’m wondering if it’s possible to Generate an enum in an Editorscript?

I have a method in an Editorscript that dynamically creates a string. Let’s say holds the strings “Foo”, “Goo” and “Hoo”. Is it possible, from that array, to generate an enum, like the following:

public enum MyEnum
{
Foo,
Goo,
Hoo
}

I guess Unity will have to recompile after that. When recompiling is done, the enum should be ready to be used in PlayMode.

Is that by any means possible?
Any input is most welcome :slight_smile:

Philomenaphiloo answered 30/8, 2023 at 11:9 Comment(2)

I have to make player a child of camera or camera to be child of player??

Bedplate

Ok , let me try it

Bedplate
P
0

Though @Default’s code works like a charm (and got me in the right direction) I ended up doing it like this:

#if UNITY_EDITOR
using UnityEditor;
using System.IO;

public class GenerateEnum
{
	[MenuItem( "Tools/GenerateEnum" )]
	public static void Go()
	{
		string enumName = "MyEnum";
		string[] enumEntries = { "Foo", "Goo", "Hoo" };
		string filePathAndName = "Assets/Scripts/Enums/" + enumName + ".cs"; //The folder Scripts/Enums/ is expected to exist

		using ( StreamWriter streamWriter = new StreamWriter( filePathAndName ) )
		{
			streamWriter.WriteLine( "public enum " + enumName );
			streamWriter.WriteLine( "{" );
			for( int i = 0; i < enumEntries.Length; i++ )
			{
				streamWriter.WriteLine( "	" + enumEntries *+ "," );*
  •  	}*
    
  •  	streamWriter.WriteLine( "}" );*
    
  •  }*
    
  •  AssetDatabase.Refresh();*
    
  • }*
    }
    #endif
Philomenaphiloo answered 6/6, 2023 at 2:36 Comment(2)

Do you get autocompletion on the created Enum in visual studio with this ?

Detrimental

Wow!!! Thanks!!! 우와!!! 감사합니다!!!

Fougere
D
0

It’s actually quite simple if you want to do this in an editor script. Like any text file, you can use a StringBuilder to create the contents:

string enumNam = "MyEnum";
string[] enumEntries = new string[] { "Foo", "Goo", "Hoo" };

StringBuilder str = new StringBuilder();
str.AppendFormat(@"public enum {0}

{
“, enumName);
for (int i = 0; i < enumEntries.Length; i++)
{
str.AppendFormat(@”{0},
", enumEntries*);*
}
str.AppendLine(@“}”);
Then, use some UnityEditor classes to get the asset path. For example:
string path = AssetDatabase.GetAssetPath(serializedObject.targetObject);
path = path.Substring(0, path.Length - Path.GetExtension(path).Length) + “.cs”;
File.WriteAllText(path, str.ToString());
AssetDatabase.ImportAsset(path);
And that should be it! (note: depending on what kind of editor script you want to write, you may need to use a different way to get the paths, but there are loads of ways to that easily found with google.

Default answered 6/6, 2023 at 2:40 Comment(1)

Neither. The Camera and the Player are 2 separate objects. Don't make either of them a parent or child. Instead, use Smooth Follow for the camera to follow the player, and if you don't have it, either import the camera stuff by going to the Assets tab, clicking Import Package, and selecting Camera. If you don't have the script, you could probably find it or something similar online.

Heeler
P
0

Though @Default’s code works like a charm (and got me in the right direction) I ended up doing it like this:

#if UNITY_EDITOR
using UnityEditor;
using System.IO;

public class GenerateEnum
{
	[MenuItem( "Tools/GenerateEnum" )]
	public static void Go()
	{
		string enumName = "MyEnum";
		string[] enumEntries = { "Foo", "Goo", "Hoo" };
		string filePathAndName = "Assets/Scripts/Enums/" + enumName + ".cs"; //The folder Scripts/Enums/ is expected to exist

		using ( StreamWriter streamWriter = new StreamWriter( filePathAndName ) )
		{
			streamWriter.WriteLine( "public enum " + enumName );
			streamWriter.WriteLine( "{" );
			for( int i = 0; i < enumEntries.Length; i++ )
			{
				streamWriter.WriteLine( "	" + enumEntries *+ "," );*
  •  	}*
    
  •  	streamWriter.WriteLine( "}" );*
    
  •  }*
    
  •  AssetDatabase.Refresh();*
    
  • }*
    }
    #endif
Philomenaphiloo answered 6/6, 2023 at 2:36 Comment(2)

Do you get autocompletion on the created Enum in visual studio with this ?

Detrimental

Wow!!! Thanks!!! 우와!!! 감사합니다!!!

Fougere
N
0

Here is youtube tutorial how to show List as Enum in inspector

158744-gif.gif

158744-gif.gif

Nessie answered 30/11, 2023 at 13:42 Comment(1)

Thank you for the suggestion, please fix the link by removing "![alt text" :)

Ionization
C
0

Another thing you may want to do is ensure the strings don’t contain any invalid characters or keywords that would break in C#. So you can combine some of the other answers here with something like this:

private static HashSet<string> csharpKeywords = new HashSet<string> {
	"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked",
	"class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else",
	"enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for",
	"foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
	"long", "namespace", "new", "null", "object", "operator", "out", "override", "params",
	"private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
	"short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
	"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using",
	"virtual", "void", "volatile", "while"
};

// given a string, attempts to make the string compatible with an enum
static string MakeStringEnumCompatible(string text)
{
	if (text.Length <= 0) { return "INVALID_ENUM_NAME"; }
	string ret = "";

	// first char must be a letter or an underscore
	if (char.IsLetter(text[0]) || (text[0] == '_')) { ret += text[0]; }

	// strip out anything that's not a digit or underscore
	for (int i = 1; i < text.Length; ++i) {
		if (char.IsLetterOrDigit(text<em>) || (text <em>== '_')) { ret += text*; }*</em></em>

* }*
* if (ret.Length <= 0) { return “INVALID_ENUM_NAME”; }
_ // all the keywords are lowercase, so if we just change the first letter to uppercase,
// then there will be no conflict*
* if (csharpKeywords.Contains(ret)) { ret = char.ToUpper(ret[0]) + ret.Substring(1); }*_

* return ret;*
* }*

Closet answered 10/7, 2021 at 0:37 Comment(1)

Would it be possible to include the sample script with the issue and a copy of the error messages with line number containing problem. Folks here can then provide better assistance.

Koo

© 2022 - 2025 — McMap. All rights reserved.