I’m trying to make a custom editor for one of my classes. This is an example of my code layout:
This snippet is taken from a script in the Assets/Editor folder.
[CustomEditor(typeof(thisScript))]
public class thisEditor : Editor {
new void OnInspectorGUI () {
target.variableX = EditorGUILayout.Toggle(" This: ", target.variableX);
}
[...]
This snippet is taken from a script in my Assets folder.
public class thisScript : MonoBehaviour {
public bool variableX = true;
[...]
My question is, Why am I getting an error saying that the definition for variableX does not exist? Did I miss a step? I followed an example and I can’t figure out a difference between my code and the example.
First of all, you should use public override void instead of new void for the OnInspectorGUI function. I don’t think it will be called properly if you use new.
The problem with the example in the editor reference page is that it’s JS, which doesn’t have the strict casting that C# has. You should cast target to thisScript:
You defined the myFingers enum within the MyScript class. If you want to access it from outside, you’ll need to use MyScript.myFingers. If you find that too long to type, you can move the public enum line before the public class line. After that, you can access myFingers without adding MyScript.
As for the other thing, yes, you will have the exact same problem (and solution, ofc) as the OP.
I have decided to keep the enum within the MyScript class otherwise I can’t reference it in the MyScriptEditor script(?). I am still having problems though. It seems that I am struggling a bit with this concept.
My MyScript class is currently as follows :
public class MyScript : MonoBehaviour
{
public enum myFingers {Eenie, Meenie, Mynie, Mo}
[....]
I have changed the MyScriptEditor class to the following :
[CustomEditor(typeof(MyScript))]
public class MyScriptEditor : Editor
{
public MyScript.myFingers selectedFinger = myFingers.Eenie;
public override void OnInspectorGUI()
{
MyScript script = (MyScript)target;
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.BeginVertical();
script.myFingers = EditorGUILayout.EnumPopup(" My Fingers : ", script.myFingers);
selectedFinger = script.myFingers;
if (selectedFinger == myFingers.Eenie)
{
[....]
}
And now I get the following error :
The culprit is the declaration of this variable :
public MyScript.myFingers selectedFinger = myFingers.Eenie;
I have tried to cast it to type of MyScript and to type of MyScript.myFingers without any success. Any ideas?
Is the only way to avoid reiterating the class name for each variable moving them out of the class? If that’s the case what is the point of this line?
[CustomEditor(typeof(MyScript))]
It just doesn’t make sense to do that if it’s not calling from the class anyway.
In java this all works from the examples I’ve seen, and everything else I read implied that it should work the same way in C#.[/code]
This line tells Unity which class the editor is for, and that is all it does. There is no way of avoiding the reiterating except by defining the enum as not part of the class.
JS simplifies a lot of syntax for the user. One of them, apparently, is automatically defining enums outside of class definitions.
An editor script defines the inspector for a specific component. Without that line, Unity doesn’t know for which component the default inspector should be replaced by the one defined in the Editor script. This is no different in JS, by the way.
Thank you for your replies. That cleared a lot up for me. I’m not happy about needing to reiterate my class for all my variables, but at least I understand now. The C# method seems far more secure, I like that.
Yes, thank you for your help tomvds, it really helped a lot. My script is working now. I still have a couple of questions but I first want to grasp this specific concept.
Edit:
Ok, I got this thing to work but not as I expected and I am still having some issues.
When I add a ObjectField …
script.hand = EditorGUILayout.ObjectField(" Hand : ", script.hand, GameObject);
…I get the following error :
I suspect it is a casting problem but I am stuck. I have added FloatFields, ToggleFields etc. without problem.
My second problem is a bit more complex.
I have declared my enumerator in my Editor script as such :
CustomEditor(typeof(MyScript))]
public class MyScriptEditor : Editor
{
public MyScript.myFingers selectedFinger = MyScript.myFingers.Eenie;
public override void OnInspectorGUI()
{
MyScript script = (MyScript)target;
EditorGUIUtility.LookLikeInspector();
EditorGUILayout.BeginVertical();
script.currentFinger = (MyScript.myFingers)
EditorGUILayout.EnumPopup(" My Fingers : ", script.currentFinger );
if (selectedFinger == MyScript.myFingers.Eenie)
{
[....]
}
and added the variable in MyScript class :
public myFingers currentFinger = myFingers.Eenie;
But now when I select one of the values of my enumerator in the Inspector, the Fields in the Inspector doesn’t change to reflect my selection, ie. :
if (selectedFinger == MyScript.myFingers.Eenie)
{
script.fingerNumber = EditorGUILayout.IntField(" Finger Number : ", script.fingerNumber);
}
else if (selectedFinger == MyScript.myFingers.Meenie)
{
script.fingerName = EditorGUILayout.TextField(" Finger Name : ", script.fingerName);
}
… it will always show the Fields only for "Eenie" even though I have selected “Meenie”.
Methods can only take variables or values (return or constant) as parameters. Specifying a type is invalid syntax.
The third parameter of ObjectField in your use needs to be a value of the type System.Type. You can use the typeof () construct to get the System.Type value corresponding to a type.
This means the correct code would be:
script.hand = EditorGUILayout.ObjectField(" Hand : ", script.hand, typeof (GameObject));
What is the purpose of the selectedFinger variable in your inspector? Get rid of it and change the if statement:
if (selectedFinger == MyScript.myFingers.Eenie)
{
to:
if (script.currentFinger == MyScript.myFingers.Eenie)
{
Thanks you for the explanation AngryAnt. I wasn’t paying proper attention to the documentation. I guess that happens when you are coding late at night without coffee
However, regarding my issues…
When I use the following line of code
script.hand = EditorGUILayout.ObjectField(" Hand : ", script.hand, typeof(GameObject));
I get the following strange error.
And regarding the second problem I had…
…it was me being dumb and blind (and tired) :roll:
That issue is resolved. Thanks again AngryAnt.
EDIT:
I was just thinking, is it possible to reference the same script, or another script, in an ObjectField? ie.
script.hand = EditorGUILayout.ObjectField(" Hand : ", script.hand, MyScript);
Ah right. I was being a bit quick on the trigger there as well. ObjectField returns the type UnityEngine.Object, so you will of-course have to cast this return value to the appropriate type (the one you gave in the typeof construct for the third parameter of the method).
You can have the ObjectField take any Unity type you like - a MonoBehaviour derived script should be fine as well.
So your code is:
script.hand = (SomeType)EditorGUILayout.ObjectField (" Hand : ", script.hand, typeof (SomeType));