Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by MichaelNielsenDev · Jul 14, 2016 at 10:58 PM · editor-scriptingeditorwindowlistseditor extensionpropertyfield

Editing a List Propertyfield in Editor Extension overwrites previously saved entries. How to fix?

I have an editor window that I am using to create new rules for a rulebook. I create rules by selecting some options, filling in some fields, etc, and then I click Save Rule.

alt text

One of those options is a Propertyfield List.

 [SerializeField]
 List<Criterion> conditionsToBeMet = new List<Criterion>();

The whole system works fine until I try to save more than one rule. What seems to happen is that editing the options for the List changes those options for the previously saved rules instead of just for the new rule I'm making. alt text

As a result, the List part of all the rules is constantly being overwritten whenever I change any part of the List.

Any ideas why this is happening and how to fix it?

Here's my code for the editor window:

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 using System.Collections.Generic;
 
 public class RuleEditor : EditorWindow {
     [SerializeField]
     List<Criterion> conditionsToBeMet = new List<Criterion>();
     string newWhoID = "someone";
     Concepts newConcept = 0;
     string combinedCriteria = "no other conditions are met";
     Responses newResponse = 0;
     string newActionValue = "some value";
 
     [MenuItem ("Window/Rulebook")]
 
     public static void  ShowWindow () {
         EditorWindow.GetWindow(typeof(RuleEditor));
     }
 
     void OnGUI()
     {
         //Add a Rule
         GUILayout.Label ("Add New Rule", EditorStyles.boldLabel);
             //Setup
         if(conditionsToBeMet.Count == 0)
         {    //If we have no criteria at all, fill in the criteria in the visualized rule display with filler text
             combinedCriteria = "no other conditions are met";
         }
         else
         {
             int index = 0;
             foreach(Criterion c in conditionsToBeMet)
             {
                 if(index != 0)
                 {    //Here we add an understandable language to show these conditions are being concatenated and thus must all be true to met the requirements for the rule
                     combinedCriteria += " and also " + c;
                 }
                 else
                 {
                     combinedCriteria = c.ToString();
                 }
 
                 //Make sure that we don't do anything illegal in Criterion construction. In other words, always make sure a min value is never greater than max.
                 if(c.minValToCompare > c.maxValToCompare)
                 {
                     c.minValToCompare = c.maxValToCompare;
                 }
 
                 //Finally, move on to the next criterion
                 index++;
             }
         }
 
             //Make sure we can see in plain text what our new Rule will look like
         GUILayout.Label ("New Rule Logic: "+"When "+newWhoID+" "+newConcept+" and "+combinedCriteria+", then "+newResponse+" by "+newActionValue, EditorStyles.label);
 
             //Start the Rule editable fields
         newWhoID = EditorGUILayout.TextField("Subject:", newWhoID);
         newConcept = (Concepts)EditorGUILayout.EnumPopup ("Condition Verb:", newConcept);
 
             //Necessary serializable stuff for PropertyField to work correctly
         ScriptableObject target = this;
         SerializedObject so = new SerializedObject(target);
         SerializedProperty criteriaProperty = so.FindProperty("conditionsToBeMet");
         EditorGUILayout.PropertyField (criteriaProperty, true);
         so.ApplyModifiedProperties();
 
             //Finish up the Rule editable fields
         newResponse = (Responses)EditorGUILayout.EnumPopup ("Response Verb:", newResponse);
         newActionValue = EditorGUILayout.TextField("Amount of Response:", newActionValue);
 
             //A button to allow the new Rule to be added to the list
         if(GUILayout.Button("Save Rule"))
         {
             //TODO: There is currently a bug where new rules will have the same Criteria list as the old rules
 
             List<Criterion> newConditions = new List<Criterion>(conditionsToBeMet);
 
             //Turn the WhoID string into an actual WhoID reference and create a new Rule from the data
             Rule newRule = new Rule (RuleLogic.GetWhoID(newWhoID), newConcept, newConditions, newResponse, newActionValue);
         }
             
         //Rule List
         GUILayout.Label ("Rulebook", EditorStyles.boldLabel);
             //Setup
         int selected = 0;
         List<string> optionsList = new List<string> ();
 
             //Show the Rule list as a pop-out drop down
         foreach(Rule rule in GlobalLists.ruleBook)
         {
             string ruleString = rule.ToString ();
             optionsList.Add (ruleString);
         }
         string[] options = optionsList.ToArray ();
         selected = EditorGUILayout.Popup("Rule List:", selected, options);
 
     }
 }
 


issue.png (68.0 kB)
editorextension.jpg (67.9 kB)
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image flashframe · Jul 14, 2016 at 11:07 PM 0
Share

I don't understand the purpose of this line

   List<Criterion> newConditions = new List<Criterion>(conditionsToBe$$anonymous$$et);
  

Shouldn't you just send conditionsToBe$$anonymous$$et, since it's already a List?

  Rule newRule = new Rule (RuleLogic.GetWhoID(newWhoID), newConcept, conditionsToBe$$anonymous$$et, newResponse, newActionValue);
avatar image MichaelNielsenDev flashframe · Jul 14, 2016 at 11:24 PM 0
Share

Earlier, I thought the problem was that, since Arrays and Lists are Reference types ins$$anonymous$$d of Value types, that maybe the fact that the new rules were using the same list instance would be the cause of why changing that instance would also change previous rules.

Unfortunately, that didn't solve the bug, but I left that there in the code in case someone suggested I use a middleman list for the data being saved to the new rule.

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Jul 15, 2016 at 12:56 AM

Well, the problem is pretty simple. You have one list instance inside your editor window "conditionsToBeMet". This list is edited by your propertyfield GUI. In there by changing the list count you will create new instances of your "Criterion" class. When you "save" / create your rule you copy the elements from your "conditionsToBeMet" list into a new lsit which is passed to the rule instance and probably saved inside the rule instance. However both lists will reference the same "Criterion" class instances. So using one list to access a Criterion instance and applying changes to it would be visible from the second List as well since they both have the same elements.

You should not copy the List into a new list but simply pass the current list to your rule and then create a new empty list:

  if(GUILayout.Button("Save Rule"))
  {
      Rule newRule = new Rule (RuleLogic.GetWhoID(newWhoID), newConcept, conditionsToBeMet, newResponse, newActionValue);
 
      // create new empty list
      conditionsToBeMet = new List<Criterion>();
  }


That way the old list and it's Criterion instances now belongs to your newRule instance and the "conditionsToBeMet" variable gets a new list for the next rule. You also might want to "reset" the other temp variables as well (newWhoID, newConcept, newResponse, newActionValue) unless you specifically want to keep them for the next rule

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MichaelNielsenDev · Jul 15, 2016 at 01:33 AM 0
Share

Yes! Thank you! That solved it.

It's really simple, like you said. I just needed to replace the list with an empty one after the rule is saved.

You really saved my bacon.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Is there a way to get all editable fields of a component in a script? 2 Answers

Is there any way to make a timeline feature in editor scripting? 1 Answer

Editor GUI text becoming misaligned 0 Answers

Error sound on key input EditorWindow OnGUI() 2 Answers

How to get PropertyDrawers in a custom EditorWindow 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges