Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

EditorWindow loses reference on play

Discussion in 'Immediate Mode GUI (IMGUI)' started by TukkerTerror, Nov 30, 2017.

  1. TukkerTerror

    TukkerTerror

    Joined:
    May 8, 2017
    Posts:
    4
    Hello, am having some problems with saving values of an EditorWindow after I press the play button the reference is gone.

    I have an abstract Class Interactible base class that contains abstract function DrawEditorSettings.
    Then I have an InteractibleImage Class that is extended by this Interactible Class.
    In the InteracitbleImage class, I override the Function DrawEditorSettings.
    And in this function, I would like to save the sprite so I could set the image sprite to the given sprite.

    Code (CSharp):
    1. public class InteractibleImage : Interactible {
    2.     [SerializeField]
    3.     private Image _image;
    4.     private Sprite _sprite;
    5.  
    6.  
    7.     // Use this for initialization
    8.     void Start () {
    9.         if(_sprite != null) {
    10.             _image.sprite = _sprite;
    11.         }
    12.         if(_image.sprite == null) {
    13.             Debug.Log("Image did not have a sprite");
    14.         }
    15.      
    16.     }
    17.     public override void DrawEditSettings(int pStartHeight, float pWindowWith) {
    18.  
    19.     GUILayout.BeginArea(new Rect(0, pStartHeight, pWindowWith, 500));
    20.         GUILayout.Label("Image", EditorStyles.boldLabel);
    21.         _sprite = (Sprite)EditorGUILayout.ObjectField(_sprite, typeof(Sprite), true);
    22.         if(_sprite == null) {
    23.             GUILayout.BeginHorizontal("box");
    24.             GUIStyle s = new GUIStyle(EditorStyles.label);
    25.             s.normal.textColor = Color.red;
    26.             GUILayout.Label("No Sprite Selected", s);
    27.             GUILayout.EndHorizontal();
    28.         } else {
    29.             GUILayout.BeginHorizontal("box");
    30.             GUILayout.Label(_sprite.texture, GUILayout.Height(100), GUILayout.Width(100));
    31.             GUILayout.EndHorizontal();
    32.             _image.sprite = _sprite;
    33.         }
    34.  
    35.         GUILayout.Label("Custom Postion : " + _customPosition.x + "," + _customPosition.y + "," + _customPosition.z);
    36.         GUILayout.BeginHorizontal("box");
    37.         EditorGUIUtility.labelWidth = 20;
    38.         _customPosition.x = EditorGUILayout.FloatField("X :", _customPosition.x);
    39.         _customPosition.y = EditorGUILayout.FloatField("Y :", _customPosition.y);
    40.         _customPosition.z = EditorGUILayout.FloatField("Z :", _customPosition.z);
    41.         transform.localPosition = _customPosition;
    42.         GUILayout.EndHorizontal();
    43.  
    44.         GUILayout.Label("Custom scale : " + _customScale.x + "," + _customScale.y + "," + _customScale.z);
    45.         GUILayout.BeginHorizontal("box");
    46.         EditorGUIUtility.labelWidth = 20;
    47.         _customScale.x = EditorGUILayout.FloatField("X :", _customScale.x);
    48.         _customScale.y = EditorGUILayout.FloatField("Y :", _customScale.y);
    49.         _customScale.z = EditorGUILayout.FloatField("Z :", _customScale.z);
    50.         transform.localScale = _customScale;
    51.         GUILayout.EndHorizontal();
    52.  
    53.         if(!_useBillBoard) {
    54.             GUILayout.Label("Custom Rotation : " + _customRotation.x + "," + _customRotation.y + "," + _customRotation.z);
    55.         }
    56.  
    57.         GUILayout.BeginHorizontal("box");
    58.         _useBillBoard = GUILayout.Toggle(_useBillBoard, "Use BillBoard");
    59.         if(_useBillBoard) {
    60.             if(GetComponent<Billboard>() == null) {
    61.                 transform.gameObject.AddComponent<Billboard>();
    62.             }
    63.             transform.localRotation = Quaternion.Euler(Vector3.one);
    64.  
    65.         } else {
    66.             if(GetComponent<Billboard>() != null) {
    67.                 DestroyImmediate(GetComponent<Billboard>());
    68.             }
    69.             _customRotation.x = EditorGUILayout.FloatField("X :", _customRotation.x);
    70.             _customRotation.y = EditorGUILayout.FloatField("Y :", _customRotation.y);
    71.             _customRotation.z = EditorGUILayout.FloatField("Z :", _customRotation.z);
    72.             transform.localRotation = Quaternion.Euler(_customRotation);
    73.         }
    74.  
    75.         GUILayout.EndHorizontal();
    76.         GUILayout.EndArea();
    77.     }
    78.  
    The function DrawEditorSettings is being called by my Script InteractibleWindow that is extended with EditorWindow.

    Code (CSharp):
    1. //C# Example
    2. using UnityEditor;
    3. using UnityEngine;
    4. using System.Collections.Generic;
    5. using System;
    6.  
    7.  
    8. public class InteractibleWindow : EditorWindow {
    9.     private VirtuscopeGameObjectBase _objectToAddInteratibleTo;
    10.     private GameObject _interactibelsParent;
    11.     private Interactible _currentInteractibleToEdit;
    12.  
    13.     private List<string> _interactiblesScriptNames = new List<string>();
    14.     private List<Interactible> _allInteractibles = new List<Interactible>();
    15.  
    16.     private int _currentInteractibleSelectedForEdit = -1;
    17.  
    18.     private int _startPointHeight = 115;
    19.     private int _heightButtons = 17;
    20.     private int _heightBetweenButtons = 8;
    21.  
    22.     void OnGUI() {
    23.         CreateInteractiblesButtons();
    24.         ShowInteractibles();
    25.         //----------------------------------------------------------------------------------------------------------------------------------------
    26.         //Get the edit infomation of the interactible that is selected
    27.         //----------------------------------------------------------------------------------------------------------------------------------------
    28.         if(_allInteractibles.Count > 0 && _currentInteractibleSelectedForEdit != -1) {
    29.             _currentInteractibleToEdit = _allInteractibles[_currentInteractibleSelectedForEdit];
    30.             _currentInteractibleToEdit.DrawEditSettings(_startPointHeight + (_allInteractibles.Count *_heightButtons + (_allInteractibles.Count * _heightBetweenButtons)), position.width);
    31.         } else {
    32.             GUILayout.Label("No interactible Select to Edit", EditorStyles.boldLabel);
    33.         }
    34.     }
    35.  
    36.     /// <summary>
    37.     /// Create buttons for every interactible and if pressed add that interactoble to the empty gameObject Interactible
    38.     /// </summary>
    39.     private void CreateInteractiblesButtons() {
    40.         GUILayout.Label("Add Interactibles to :" + _objectToAddInteratibleTo.gameObject.name, EditorStyles.boldLabel);
    41.         for(int i = 0; i < _interactiblesScriptNames.Count; i++) {
    42.             if(GUILayout.Button("Add " + _interactiblesScriptNames[i], GUILayout.Height(_heightButtons))) {
    43.                 GameObject interactible = PrefabUtility.InstantiatePrefab(Resources.Load(_interactiblesScriptNames[i])) as GameObject;
    44.                 if(interactible != null) {
    45.                     if(_interactibelsParent != null) {
    46.                         interactible.transform.parent = _interactibelsParent.transform;
    47.                         interactible.transform.localPosition = Vector3.zero;
    48.                         interactible.transform.localRotation = Quaternion.identity;
    49.                         _currentInteractibleToEdit = interactible.GetComponent<Interactible>();
    50.                         _objectToAddInteratibleTo.AddInteractibleToList(interactible.GetComponent<Interactible>());
    51.                     } else {
    52.                         Debug.Log("interactible parent was null");
    53.                         DestroyImmediate(interactible);
    54.                     }
    55.                 } else {
    56.                     Debug.LogError("not correct prefab");
    57.                 }
    58.             }
    59.         }
    60.     }
    61.  
    62.  
    63.     /// <summary>
    64.     /// Set Correct values for the window mathing with the object selected
    65.     /// </summary>
    66.     /// <param name="pObject"></param>
    67.     public void SetValues(VirtuscopeGameObjectBase pObject) {
    68.         _objectToAddInteratibleTo = pObject;
    69.         _objectToAddInteratibleTo.UpdateInteractblesList();
    70.         _interactiblesScriptNames.Clear();
    71.      
    72.        
    73.         //----------------------------------------------------------------------------------------------------------------------------------------
    74.         //Get all the Interactibles that are in the folder Interactibles and add those to the list for the CreateInteractiblesButtons function
    75.         //----------------------------------------------------------------------------------------------------------------------------------------
    76.         string[] res = System.IO.Directory.GetFiles(Application.dataPath+ "/Scripts/Interactibles");
    77.         for(int i = 0; i < res.Length; i++) {
    78.             string part = res[i].Substring(res[i].IndexOf(@"\") + 1);
    79.             if(!part.Contains("meta")) {
    80.                 if(part.Contains(".cs")) {
    81.                     _interactiblesScriptNames.Add(System.IO.Path.GetFileNameWithoutExtension(part));
    82.                 }
    83.             }
    84.         }
    85.        
    86.         for(int i = 0; i < _objectToAddInteratibleTo.gameObject.transform.childCount; i++) {
    87.             if(_objectToAddInteratibleTo.gameObject.transform.GetChild(i).name == "Interactibles") {
    88.                 _interactibelsParent = _objectToAddInteratibleTo.gameObject.transform.GetChild(i).gameObject;
    89.                 ShowInteractibles();
    90.                 return;
    91.             }
    92.         }
    93.         GameObject interactibles = new GameObject("Interactibles");
    94.         interactibles.transform.parent = _objectToAddInteratibleTo.gameObject.transform;
    95.         interactibles.transform.localPosition = Vector3.zero;
    96.         interactibles.transform.localRotation = Quaternion.identity;
    97.         _interactibelsParent = interactibles;
    98.  
    99.     }
    100.  
    101.     /// <summary>
    102.     /// Show the interactibles that are a child of the empty gameObject Interactbles to select one to edit
    103.     /// </summary>
    104.     private void ShowInteractibles() {
    105.         //----------------------------------------------------------------------------------------------------------------------------------------
    106.         //show all the interactibles and show the show the current one that is beeing edited
    107.         //----------------------------------------------------------------------------------------------------------------------------------------
    108.         GUILayout.Label("Interactibles to Edit :", EditorStyles.boldLabel);
    109.         GUILayout.Box("", new GUILayoutOption[] { GUILayout.ExpandWidth(true), GUILayout.Height(1) });
    110.         _objectToAddInteratibleTo.UpdateInteractblesList();
    111.         _allInteractibles = _objectToAddInteratibleTo.Interactibles;
    112.         var skin = new GUIStyle(GUI.skin.button);
    113.  
    114.  
    115.         if(_allInteractibles.Count > 0) {
    116.             for(int i = 0; i < _allInteractibles.Count; i++) {
    117.                 GUILayout.BeginHorizontal("box");
    118.                 if(_currentInteractibleSelectedForEdit != i && _currentInteractibleSelectedForEdit != -1) {
    119.                     //GUI.color = Color.blue;
    120.                     if(_currentInteractibleSelectedForEdit ==i) {
    121.                         if(GUILayout.Button("settings of :" + _allInteractibles[i].transform.name,skin, GUILayout.Height(_heightButtons))) {
    122.                             _currentInteractibleSelectedForEdit = i;
    123.                         }
    124.                     } else {
    125.                         //GUI.color = Color.white;
    126.                         if(GUILayout.Button("settings of :" + _allInteractibles[i].transform.name, skin, GUILayout.Height(_heightButtons))) {
    127.                             _currentInteractibleSelectedForEdit = i;
    128.                         }
    129.                     }
    130.                 } else {
    131.                     if(_currentInteractibleSelectedForEdit != -1) {
    132.                         GUI.color = Color.green;
    133.                     }
    134.                     if(GUILayout.Button("settings of :" + _allInteractibles[i].transform.name, skin, GUILayout.Height(_heightButtons))) {
    135.                         _currentInteractibleSelectedForEdit = i;
    136.                     }
    137.                     GUI.color = Color.white;
    138.                 }
    139.                 if(GUILayout.Button("Remove Interactible" , skin, GUILayout.Height(_heightButtons))) {
    140.                     _currentInteractibleToEdit = null;
    141.                     _currentInteractibleSelectedForEdit = -1;
    142.                     _objectToAddInteratibleTo.RemoveInteractble(_allInteractibles[i],i);
    143.                 }
    144.                 GUILayout.EndHorizontal();
    145.             }
    146.         } else {
    147.             _currentInteractibleSelectedForEdit = -1;
    148.         }
    149.         GUILayout.Box("", new GUILayoutOption[] { GUILayout.ExpandWidth(true), GUILayout.Height(1) });
    150.  
    151.     }
    152. }  
    153.  
    Here is where the sprite was set in the EditorWIndow.

    Here you can see that the reference of the image was set to the given sprite.

    And here you can see that is lost my reference.


    Thanks in advance for helping me.
     
  2. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,188
    I couldn't look at all of your code in detail, so I'm guessing, but I hope it still helps. It looks like you are setting an object reference on a component via code. To save this change, you must tell Unity that this component (and scene or prefab) is now dirty. Unity recommends using Undo.RecordObject() for this. It will record an undo action, but also set the scene dirty. Other than that, when doing editor scripting, I would recommend using SerializedProperties and the functionality of the SerializedObject class. If you edit the object via SerializedProperty, you get undo and prefab overrides (the bold text variables on prefab instances, which have changed from the original prefab), for free. If you really need to, you can also set a scene dirty via EditorSceneManager.MarkSceneDirty() and in some specific instances, you can also set an asset dirty with EditorUtility.SetDirty().
     
    FlightOfOne and TukkerTerror like this.
  3. TukkerTerror

    TukkerTerror

    Joined:
    May 8, 2017
    Posts:
    4
    FlightOfOne likes this.
  4. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    668
    In my case it was because I was using on prefab. I should probably use SerializedProperties.

    But I ended up just applying it to the prefab in this instance.
    Code (CSharp):
    1.   PrefabUtility.ApplyPrefabInstance(targetScript.gameObject, InteractionMode.UserAction);
    Thank you!
     
    Last edited: Jun 25, 2020