Search Unity

Question SerializedProperty not allowing modification.

Discussion in 'Scripting' started by Foursee, Dec 7, 2022.

  1. Foursee

    Foursee

    Joined:
    Feb 25, 2020
    Posts:
    1
    I'm trying to create a unity localization tool using scriptable objects for a school project. So far, I can modify the language at runtime using:

    Code (CSharp):
    1. [CreateAssetMenu(fileName = "Language", menuName = "Language")]
    2. public class LanguageDictionary : ScriptableObject
    3. {
    4.     // Since dictionaries aren't serializable in Unity, we define our own define a serializable entry class
    5.     [System.Serializable]
    6.     public class LanguageEntry
    7.     {
    8.         public string key;
    9.         public string value;
    10.     }
    11.  
    12.     [SerializeField]
    13.     public List<LanguageEntry> languageEntries;
    14. }
    Code (CSharp):
    1. // Handles localization within editor
    2. public class Localizer : MonoBehaviour
    3. {
    4.     public LanguageDictionary language;
    5.     public List<TextMeshProUGUI> textBoxes;
    6.  
    7.     void Update()
    8.     {
    9.         UpdateText();
    10.     }
    11.  
    12.     // Update text boxes
    13.     void UpdateText()
    14.     {
    15.         // For every text box...
    16.         foreach (TextMeshProUGUI textBox in textBoxes)
    17.         {
    18.             // Find corresponding language entry
    19.             foreach (LanguageDictionary.LanguageEntry entry in language.languageEntries)
    20.             {
    21.                 if (textBox.name == entry.key)
    22.                 {
    23.                     textBox.text = entry.value;
    24.                 }
    25.             }
    26.         }
    27.     }
    28.  
    29.     public void ChangeLanguage(LanguageDictionary lan)
    30.     {
    31.         language = lan;
    32.         UpdateText();
    33.     }
    34. }
    I'm now trying to create an editor tool that allows the user to add/delete/modify these language scriptable objects. Here's what I have so far:

    Code (CSharp):
    1. // Main window, allows us to view/modify/create languages
    2. public class LocalizationEditor : EditorWindow
    3. {
    4.     public static LanguageDictionary currentLanguage;
    5.     public static List<LanguageDictionary> languages;
    6.     public int languageIndex = 0;
    7.  
    8.     private static List<GameObject> canvases;
    9.     private static LanguageDictionary defaultLanguage;
    10.  
    11.     // Open localization window
    12.     [MenuItem("Window/Localization")]
    13.     static void OpenWindow()
    14.     {
    15.         LocalizationEditor window = (LocalizationEditor)GetWindow(typeof(LocalizationEditor));
    16.         window.minSize = new Vector2(400, 200);
    17.         window.Show();
    18.         // Initialize default language as well as our canvases
    19.         defaultLanguage = Resources.Load<LanguageDictionary>("Languages/English");
    20.         currentLanguage = defaultLanguage;
    21.         canvases = GameObject.FindGameObjectsWithTag("Localized Canvas").ToList();
    22.     }
    23.  
    24.     void OnGUI()
    25.     {
    26.         UpdateText();
    27.         GetLanguages();
    28.         DrawEditor();
    29.     }
    30.  
    31.     // Update text boxes
    32.     void UpdateText()
    33.     {
    34.         // Setting text box values in each canvas if canvas exists
    35.         if (canvases != null)
    36.         {
    37.             foreach (GameObject canvas in canvases)
    38.             {
    39.                 canvas.GetComponent<Localizer>().language = currentLanguage;
    40.             }
    41.         }
    42.     }
    43.  
    44.     // Get all language SOs and add them to our language list
    45.     void GetLanguages()
    46.     {
    47.         languages = Resources.LoadAll("Languages", typeof(LanguageDictionary)).Cast<LanguageDictionary>().ToList();
    48.     }
    49.  
    50.     // Draw our editor elements
    51.     void DrawEditor()
    52.     {
    53.         // Current language selector
    54.         EditorGUILayout.BeginHorizontal();
    55.         GUILayout.Label("Current Language");
    56.         // Convert our language list into an array of strings
    57.         string[] popupStrings = languages.ConvertAll(x => x.ToString()).ToArray();
    58.         // Convert selected index into corresponding LanguageDictionary
    59.         languageIndex = EditorGUILayout.Popup(languageIndex, popupStrings);
    60.         currentLanguage = languages[languageIndex];
    61.         EditorGUILayout.EndHorizontal();
    62.  
    63.         // ERROR HERE
    64.         // CAN ADD ENTRIES BUT CANT CHANGE PREXISTING?
    65.         // Current language details
    66.         EditorGUILayout.BeginHorizontal();
    67.         GUILayout.Label("Dictionary");
    68.         EditorGUILayout.EndHorizontal();
    69.         // Update serializable object for our language
    70.         EditorGUILayout.BeginHorizontal();
    71.         SerializedObject serializedObject = new SerializedObject(currentLanguage);
    72.         // Retrieve entries and values from language
    73.         SerializedProperty entries = serializedObject.FindProperty("languageEntries");
    74.         // Create property field then apply properties
    75.         EditorGUILayout.PropertyField(entries);
    76.         serializedObject.ApplyModifiedProperties();
    77.         EditorGUILayout.EndHorizontal();
    78.  
    79.         // Language creator window
    80.         EditorGUILayout.BeginHorizontal();
    81.         if (GUILayout.Button("Create Language", GUILayout.Height(40)))
    82.         {
    83.             AddLanguageEditor.OpenWindow();
    84.         }
    85.         EditorGUILayout.EndHorizontal();
    86.     }
    The problem lies near line 63: I can add/delete the language entries, however when trying to modify the value attributes of preexisting entries they simply snap back to their original values and do not save.

    I'm assuming the problem lies in me creating a SerializedProperty for the entry, but not for the entries specific key value pairs?

    I've also attached an image of what my editor setup looks like so far.

    Any help would be appreciated!
     

    Attached Files:

    Last edited: Dec 8, 2022