Search Unity

Persistent changes to inspector fields of pre-placed scene objects via editor script

Discussion in 'Immediate Mode GUI (IMGUI)' started by moco2k, Jun 30, 2017.

  1. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Hey everyone,

    I hope you can help me with the following issue.

    I have a scene with preplaced waypoints. For each waypoint, I want to assign a unique id. Notably, I want to specify this id already in the editor, not during game runtime. Of course, I could do this manually by just setting a unique id for each waypoint by hand. However, because of the high number of waypoints, this is a very cumbersome and inefficient solution. Thus, instead, I want to use a simple editor script to automatically assign an id to each waypoint. So, I have implemented a custom editor window with a button. The button runs a script that finds all waypoints in the scene with FindGameObjectsWithTag. Then, the script iterates over all found waypoints and does something like

    Waypoint wp = waypointsInScene .GetComponent<Waypoint> ().SetId(i+1);

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEditor.SceneManagement;
    6.  
    7. namespace DwarvenMonsterSlayers
    8. {  
    9.     public class IdGenerator : EditorWindow
    10.     {
    11.         [MenuItem ("Window/Waypoint ID Generator")]
    12.  
    13.         public static void  ShowWindow () {
    14.             EditorWindow.GetWindow(typeof(IdGenerator));
    15.         }
    16.  
    17.         void OnGUI ()
    18.         {
    19.             if(GUILayout.Button("Generate IDs"))
    20.             {
    21.                 EditorSetWaypointIds ();
    22.             }
    23.         }
    24.  
    25.         void EditorSetWaypointIds()
    26.         {
    27.             GameObject[] waypoints = GameObject.FindGameObjectsWithTag(DwarvenMonsterSlayers.Constants.TAG_WAYPOINT);
    28.  
    29.             for (int i = 0; i < waypoints.Length; i++)
    30.             {
    31.                 Waypoint wp = waypoints [i].GetComponent<Waypoint> ();  
    32.                 if (wp != null)
    33.                     wp.SetId( i+1 );
    34.             }
    35.  
    36.             EditorSceneManager.MarkSceneDirty (EditorSceneManager.GetActiveScene ());  
    37.         }
    38.     }
    39. }

    After running the script, I notice that it works and the id's of all waypoints have been properly set.
    However, after I close and reload the scene, the id values of all waypoints are set back to default (0). So, it seems that the id changes are succesfully applied during editor runtime, but they are not saved persistently. It can also be noticed that the id fields are not marked as bold in the inspector after the script has run, and also the overall scene is not set dirty. So, the unity editor inspector has not noticed that the id's have been changed as it would be the case if I would have changed the fields by hand.

    I have tried to add the following line of code, but it does not help.
    EditorSceneManager.MarkSceneDirty (EditorSceneManager.GetActiveScene ());

    So, I am afraid that I am missing an important step here so that the changes are saved.
    Or, do I need to create a full custom inspector window so that the changes are made persistent?
    In fact, I do not need any custom fields, I just want to set inspector fields by script.

    Any help is much appreciated!
    Thanks in advance :)
     
    Last edited: Jul 1, 2017
  2. PsyKaw

    PsyKaw

    Joined:
    Aug 16, 2012
    Posts:
    102
    Can you post Waypoint code please ?
     
  3. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Yepp. I have reduced it to the the relevant part. It's like this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [System.Serializable]
    6. public class Waypoint : MonoBehaviour
    7. {
    8.     [SerializeField]
    9.     public int id;
    10.  
    11.     ...
     
  4. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    294
    Okay, I think I have just found the solution. It seems to work when I add the following line of code right after I change the id: EditorUtility.SetDirty (wp);

    Alternatively, putting Undo.RecordObject (wp, "set id wp"); right before the id change works as well. According to the docs, this seems to be the preferable solution.
     
    Last edited: Jul 1, 2017