Custom Editors

I’m writing a custom editor for my scene transition portals, so that I can select the destination scene from a dropdown list which is populated with the names of all scenes available in the build editor, rather than relying on a string field for scene name (or integer for build index).

I’ve got the dropdown list working, but for some reason the values that I choose from the lists (both for this and for the target portal identifier enum) don’t seem to be being saved correctly, and are forgotten as soon as I press Play or change scenes.

I’ve tried using serializedObject.Update() and serializedObject.ApplyModifiedProperties(), with no luck. I’ve tried using Undo.RecordObject(portal), which a) only works if you actively save the scene before you press Play and b) only seems to work for the target scene field, but not for the enum values.

Any other suggestions?

My custom editor code is below:

[CustomEditor(typeof(Portal))]
public class PortalInspector : Editor
{
    private Portal portal;
    private string[] scenes;
    private int sceneIndex = 0;

    private void OnEnable() {
        portal = (Portal)target;
        scenes = GetSceneNames();
    }

    public override void OnInspectorGUI() {
        //serializedObject.Update();
        Undo.RecordObject(portal, "changes to Portal");

        EditorGUILayout.LabelField("Identifier", EditorStyles.boldLabel);
        portal.identifier = (Portal.PortalIdentifier)EditorGUILayout.EnumPopup("Identifier", portal.identifier);

        EditorGUILayout.LabelField("Destination", EditorStyles.boldLabel);
        sceneIndex = EditorGUILayout.Popup("Target Scene", sceneIndex, scenes);
        portal.sceneToLoad = scenes[sceneIndex];
        portal.targetPortal = (Portal.PortalIdentifier)EditorGUILayout.EnumPopup("Target Identifier", portal.targetPortal);

        //serializedObject.ApplyModifiedProperties();
    }

    private string[] GetSceneNames() {
        //This populates a string array with the names of the scenes from the Build Settings
        //It also initialises sceneIndex with the index of the saved sceneToLoad
    }
}

My Portal class has the following interface (i.e. the fields are public, so I don’t know why they aren’t being serialized):

public class Portal : MonoBehaviour
{
    public enum PortalIdentifier { None, A, B, C }

    public PortalIdentifier identifier = PortalIdentifier.A;
    public string sceneToLoad = "";
    public PortalIdentifier targetPortal = PortalIdentifier.None;

    //Triggering code etc...
}

@sampattuzzi

Although this is out of the scope of the course i dont know how much support we can give but its a littel over my head as i am still learning this too!

I’ve got a lecture that @Marc_Carlyon is reviewing now that will answer this question. Want to hang on till that one is published? I’m sure Marc will let you know that it’s out.

The gist is that you need to use SerializedObject and SerializedProperty to edit the serialized values. There’s an excellent example of exactly what you’re trying to do in the 2D Game Kit.

But remember that just because you have an editor to select the scene doesn’t mean your reference wont break if the scene is renamed.

2 Likes

Cool, thanks Sam! I’ll keep an eye out for that lecture when it becomes available.

That’s a good point about the scene being renamed, maybe better to display the scene names as string but keep sceneToLoad as a build index int, since that’s less likely to change.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms