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 Thomas-Slade · Oct 17, 2016 at 05:00 AM · prefabserializationoverrideundodirty

Using Undo.RecordObject() does not protect a component's variables from being reverted to the prefab on play.

I'm working on a custom editor script that takes an XML file of items ('trade items': I'm working on a game about the silk road), and populates the lists in the Market.cs components that are attached to each city in the game. I'm doing this because I want each market to have a supply/demand value for each good, e.g. Gold : 3.4, Silk: 8.6. I want to be able to add new trade items to my XML file, then load that file into my Markets.

Markets are a component of a trade node, basically a city. Naturally, these are instances of a prefab, so that I can edit all trade nodes at once. I use a custom editor window to load the XML data and use it to populate the Market lists:

 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 using Trade;
 
 public class Builder : EditorWindow
 {
     // Make a custom editor window with a button that says "Build Markets"
     // This button calls the BuildMarkets() function.
 
     // Initialises serialized data in market objects.
     void BuildMarkets()
     {
         Market[] markets = FindObjectsOfType<Market>();
 
         Debug.Log(markets.Length + " markets found. " + World.Instance.goods.goods.Count + " varieties of good found. Populating markets.");
 
         // Add a supply value for each good, in every market.
         foreach (Market m in markets)
         {
             // Record undo change (ensures the change will be 'set to dirty' and won't revert to the prefab on play).
             Undo.RecordObject(m, "Build Market Supplies");
 
             foreach (Good g in World.Instance.goods.goods)
             {
                 // Note that you can't refer to the supply's dictionary, or use ContainsKey(), because
                 // the dictionary does not exist until runtime. Use the key list instead.
                 if (!m.supplies.keys.Contains(g))
                 {
                     Debug.Log(m.gameObject + "'s Market does not contain an entry for " + g.name + ".");
                     m.supplies.dictionary.Add(g, 0.0f);
                 }
             }
         }
     }
 }

It's worth mentioning that I needed my Market's supplies list to be a dictionary, so that I could easily search through it. Dictionaries can't be serialised, so I followed the typical example of creating a custom serializeable Dictionary seen here. As far as I can tell it's working fine, and is not part of the issue.

When I hit the "Build Markets" button, the supplies list is populated with my XML goods as I'd want. However, on clicking play, these lists revert to the prefab value: no members, and a length of 0. When the game is stopped, the values are still gone.

As you might imagine, when I use the "Build Markets" function, the Market data shown in the inspector does not turn bold, as other things in Unity do when they're set as something different from their prefab. The fix recommended in the documentation is to use Undo.RecordObject(). So I tried this, as seen in my code. This sets the lists I need serialised to 'dirty' bold font in the inspector, but not their elements, like so:

alt text

But what I need is for the lists components - basically anything that has been changed - to be protected from the prefab override. Why isn't Undo.RecordObject() doing this?

One thing I've noticed is that if I really fiddle around with stuff - repeatedly clearing the lists, rebuilding them, and clicking on the inspector lots of times, I do manage to get all of the list elements set to dirty as well.

Finally, I'm aware that SetDirty() sets an entire component to dirty, but this is far from convenient. It's likely that I'll need some variables in any given component to be dependant on the prefab.

serializationproblem.png (28.7 kB)
Comment
Add comment
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

0 Replies

· Add your reply
  • Sort: 

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Does Undo.RecordObject support marking ScriptableObjects dirty? 2 Answers

Possible to make "override all" button on prefab instances ignore certain values (like it does for position)? 0 Answers

Saving runtime created avatar 1 Answer

undo redo + custom serialization slow 0 Answers

Unity setting SerializedProperty.prefabOverride incorrectly 2 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