I would like to ask for a reference to an object in the scene via the editor through a custom editor script. I use EditorGUILayout.ObjectField like this:
public class aClass : Editor
{
private GameObject _targetObject = null;
public override void OnInspectorGUI()
{
_targetObject = (GameObject)EditorGUILayout.ObjectField("Target Object", _targetObject, typeof(GameObject), true);
}
It works fine when I drag-drop an object onto _targetObject, but if I select any other GO in the hierarchy view, _targetObject becomes null again. Possibly a Unity 4 bug?
You’re assigning your GameObject to a non-serialized member, and thus it could become null at any time (mainly because of Unity refreshing or the Inspector window being enabled/disabled/re-enabled). If you want to be sure it’s not nulled while you still need it, you’ll have to serialize it by either making it public or using the [SerializedField] attribute.
EDIT: P.S. to serialize it correctly, you should place that variable in the target you’re inspecting
It has nothing to do with it being public, serializable, or private.
@OP You seem to be getting confused between how an EditorWindow behaves and how an Editor behaves. Review the documentation on those classes again might help (although its not particularly clear).
Maybe add this code to your editor class to get an idea of what is happening:
public aClass () {
Debug.Log ("boom");
}
And yes I am being cryptic because its always good to find stuff out yourself.
@JohnnyA: please don’t be cryptic I don’t get what the difference between an EditorWindow and an Editor has to do with this issue, and I’m curious now.
An Editor classes lifetime is only the time that the editor is open. i.e. new ones get instantiated each time you click on a game object. You typically store the values for an editor in the target object (the special case of SerializedProperty still gets its value from the target object, it just does some nice things to handle Undo, etc automatically).
I contrasted to EditorWindow because the example for EditorGUILayout.ObjectField uses an EditorWindow. An editor window has a much longer lifetime and you generally store values for the editor window in the editor window class itself.
I pointed to the doco because a quick perusal reveals that variables are not used in the editor class examples and there is a little discussion about modifying the targets variables directly vs SerializedProperties.
Indeed it doesn’t. I could make the variable anything else and it would still behave the same.
Ok, however, I am unsure why I should have to create an entire EditorWindow while the Unity inspector itself simply uses “Editor” when exposing a GameObject variable and allowing reference-binding (Unity internally uses UnityGUI as well to show the inspector).
Im not sure how a Debug.Log helps here. What exactly will a “boom” indicate?
Sincere thanks, however, it might help to know that I am not new to Unity, programming, editor scripts, or learning on my own.
All said, I am not storing an object, I am storing the “reference” to an object, which is assigned via the editor. I would rather not store this reference directly in target because I need to perform some computations on the referenced gameobject before passing on a value to the target. Why an editor cannot maintain a reference to an object between a selection and re-selection is beyond me.
From what I understand, JohnnyA says an EditorWindow has a longer lifetime than Editor, hence a “refresh” in Editor causes the stored references to be lost while EditorWindow would preserve them.
However, I tried the same code using EditorWindow, and the same thing results…i.e, references are lost. Or perhaps I am missing something?
An Editor gets re-initialized each time its target is selected (if it was previously deselected). An EditorWindow instead has a longer life, but gets re-initialized too in some conditions (like when reloading the project, refreshing some scripts, or closing and re-opening the window). That said, if you tried that code in an EditorWindow, and the reference got lost just by selecting another object while the window was still open, something strange is happening.
Ah wait…thats probably it. I haven’t kept the window open…Though its still perplexing that the native unity inspector manages to store references just fine using an “Editor” while we need to create a window that stays open…
Unity Inspectors don’t store any reference inside an Editor class: they just access them via the serialized fields of their targets. When you change some parameter of a Light, for example, your’re actually changing a serialized member in the Light Component, not in the Light Inspector.
I didn’t say use an EditorWindow, I said that when you use an Editor you store the values in the target object itself (the object being edited) not in the editor class.
The adding of the constructor shows clearly that every time you click on the object a new editor is constructed. i.e. You wont retain your old values.