- Home /
Why i don't see the button in the Inspector on debug mode ?
I have this button script:
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(LevelMap))]
public class CustomButton : Editor
{
public override void OnInspectorGUI()
{
LevelMap Generate = (LevelMap)target;
if (GUILayout.Button("Generate Map"))
{
Generate.GenerateNew();
}
}
}
And a script that is attached to a empty GameObject the Level Map:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[ExecuteInEditMode]
public class LevelMap : MonoBehaviour
{
public GameObject Node;
public Vector3 nodeSize;
public int Rows;
public int Columns;
public int mapWidth;
public int mapHeight;
public float Spacing = 2.0f;
public float spawnSpeed = 0;
private void Start()
{
Generate();
}
private void Generate()
{
for (int x = 0; x < mapWidth; x++)
{
for (int z = 0; z < mapHeight; z++)
{
GameObject block = Instantiate(Node, Vector3.zero, Node.transform.rotation) as GameObject;
block.transform.parent = transform;
block.transform.localPosition = new Vector3(x, 0, z);
}
}
}
public void GenerateNew()
{
Generate();
}
}
One of the problems is that in the Inspector if the mode is normal i see the Generate Button. But i don't see the public variables of Level Map. If i change the mode to Debug then i will see the Level Map public variables but i will not see the button.
How can i make that i will see the button and the variables at the same mode ? (normal or debug)
Another problem is how can i make that if generated a new map now if i will change one or more of the variables values in the editor it will effect the GenerateMap in real time ? For example if i change the Spacing variable value if it was for example 2 and i change it to 4 then generate a new map but with spacing 4.
So the button is like for reset to generate whole new map but changing variables values will effect the current map only.
Answer by FlaSh-G · Aug 11, 2017 at 10:54 PM
The inspector's debug mode's express purpose is to not display any regular editor GUI, but rather display as many of the components' fields as possible. As the name suggests, the debug mode is only for debugging components, not for regular use.
To let your custom inspector gui display the default UI as if there was no editor class, you can use DrawDefaultInspector like this:
public override void OnInspectorGUI()
{
LevelMap Generate = (LevelMap)target;
if (GUILayout.Button("Generate Map"))
{
Generate.GenerateNew();
}
DrawDefaultInspector();
}
That's true. However the whole approach seem to be just wrong. First of all the button in the inspector just triggers a runtime methods of the component. This can be implemented simply as context menu item. So it doesn't require any editor script in the first place.
Next is that almost 90% when i see the use of "ExecuteInEdit$$anonymous$$ode" it's actually used in a wrong / problematic way. That attribute is ment to provide "runtime behaviour" at edit time. Though this should only be used to provide the user with a visual representation. So it makes sense to use it for simulating particle systems or a water wave simulation to show how they will look at runtime. Code that actually edits / modifies the scene shouldn't be executed by such a script.
When you use ExecuteInEdit$$anonymous$$ode, Start will be called each time the scene is loaded during edit time. Since you don't clean up your old objects you will create additional objects each time Start is called during edit mode. Start is also called after an assembly reload which happens each time a script got changed outside of Unity and Unity recompiles it's project assemblies..
You shouldn't use ExecuteInEdit$$anonymous$$ode at all in this case. Just call your Generate method once from the Reset callback. Reset is called only once when the object is created (or when you select "Reset" from the context menu). In addition you can simply add a Context$$anonymous$$enu to allow the user to manually trigger the creation. Also the code probably should remove the old objects (if there are any) before creating new objects.
I tried in the bottom of the script $$anonymous$$ap Level to add:
[Context$$anonymous$$enu("Generate $$anonymous$$ap")]
void GenerateNew()
{
for (int i = 0; i < objects.Count; i++)
{
DestroyImmediate(objects[i]);
}
Generate();
}
But i don't see it in the inspector. Also when running the game i don't see it.
I also remove the the line: [ExecuteInEdit$$anonymous$$ode]
Then i tried to add to the bottom:
[UnityEditor.$$anonymous$$enuItem("GameObject/UI/Text Area", false, 10)]
public static void GenerateNew()
{
for (int i = 0; i < objects.Count; i++)
{
DestroyImmediate(objects[i]);
}
Generate();
}
But then i need to change everything to be static including the transform it self.
So i'm trying to make all the suggestions you gave me but so far not working. Could you show me please how to do the whole suggestions ?
Valid points by @Bunny83 here. I totally ignored all this in the posted script.
The proposed context menu entry is supposed to completely replace the inspector. Should look something like this:
This is the only point I'd disagree with @Bunny83 on. If you want to call a non-static method on a specific object, drawing an extra button into the inspector is totally fine. If that method should also be called on runtime, it's also totally fine to call that method from the editor script ins$$anonymous$$d of re-implementing it for the editor.
Even if it's only supposed to be called in editor, it might be valid to implement it in the runtime class for the sake of loose coupling.
So, depending on your situation, stay with the custom inspector code, it's fine. The ExecuteInEdit$$anonymous$$ode however should definitely go.
I didn't say that implementing a custom inspector to add such a button is wrong, just unnecessary. I said:
This can be implemented simply as context menu item. So it doesn't
require any editor script in the first place.
ps: The context menu item adds an item to the context menu of the component, not to the window menu: