Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

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,186
    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:
    659
    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