Search Unity

As some of you may know, we built most of the new UI System as user scripts. That means we were subject to most of the limitations our users face when developing systems in Unity and extending the editor. Throughout the development we’ve been fixing the issues we came across. Today we would like to highlight one of them.

One of the problems we faced was how could we rename fields without having our users lose data. During our beta period, we wanted to refactor our code without breaking our beta users projects, so they could continue testing each new version without having to worry about data loss and project breakage. To solve that we introduced the [FormerlySerializedAs] attribute.

What can you do with it? Let’s look at some use cases for it!

Variable renaming

Let’s say you have the following class:

 

But you would like to rename m_MyVariable to something else like m_ABetterName, but you don’t want your users to have to re-populate the data for this MonoBehaviour in all of their scenes and/or prefabs. You can now accomplish that like this:

Encapsulating public API

In this case, you have a public field that is part of your API, but would like to encapsulate it in an accessor. So let’s assume we have a class MyClass like this:

To encapsulate this value in an accessor without losing any existing data in your assets you can do something like this:

Multiple Renames

Renaming fields multiple times is supported, just add the attribute multiple times, one for each name of the previous names of the field:

When can I remove the attribute?

You can remove the attributes after you have re-saved all of your scenes and assets, after the rename. Of course this implies you have ‘control’ of your users. For some, like the Asset Store publishers for instance, this ‘control’ is impossible. So in this case you will have to keep it as long as you want to make sure people with any version of your code can upgrade to your new code without losing data.

Hope you find this new little feature helpful!

30 Comments

Subscribe to comments

Comments are closed.

  1. Steffano (Stiffix)

    March 19, 2015 at 11:33 pm

    I can’t say enough how many times I needed it. Thank you

  2. Thanks, this is awesome addition! Every Asset Store developer should keep it in mind.

  3. This new renaming attribute is sounding like a great direction! One related thing that often happens is wanting to change the units of a particular serialized property – like a float representing milliseconds suddenly wanting to represent seconds at an artists request. It would be awesome if these rename attributes (or maybe a new attribute) let you supply an optional “upgrade” function that can actually convert the old data to the new data, so you could supply conversions in code where necessary. Is this something other people have wanted?

  4. Excellent new feature. Ohh, how can I do not keep loving the Unity? :D

  5. Cool !

  6. Very useful small feature indeed !

  7. [FormerlySerializedAs(“Prince”)]
    [SerializeField]
    private string TheArtist;

    Seriously useful feature!

  8. Awesome feature guys! Especially the fact this work on Serializable classes!

    Any chance we’re eventually going to get full ‘dynamic’ keyword support for classes? Then we can safely remove fields from our SaveFiles with worrying about them blowing up on Deserialize.

  9. These “small changes” or “small additions” are really what I like most about Unity. Not being able to do that kind of refactoring was a rather significant limitation and I think adding this new attribute fixes that limitation quite nicely. Right on!

  10. Simple renaming is nice and fun but basically it is far not enough in bigger projects that spans over longer development time. We need re-typing, changing of default values, changing of whole data structures, mergability, human readability, external-tool-readability, easier to parse in random access order etc.

    (Of course, some of these points are conflicting. We want different aspects in different types of assets)

    We start to abandon unity save format here, for its lack of extendability in any of these points and switch to our own format :(. Unfortunately, that’s also a pain in the neck, as Unity does not provide any kind of helping hands in this direction either..

    Here is my 2c idea that I posted in a somewhat related issue report (665302):
    —-

    I would recommend to have a post-save in the editor. This step gets the save data as structured input (like key/value pairs. The SerializedObject data format seems perfect – if its not bound to concrete object Types?) and can start to optimize the structure of the data for several things like “mergability”.

    Mirrored to that, there is a pre-load step that first “restores” the data before it is passed to the current deserialization data mapping.

    This approach makes it far more easier to optimize the save file format for various different things independend of the internal data representation. There are many conflicting goals that an export format should look like. Speed, size, human readability, mergability, random-access-reading, easiness to analyse with other tools…

    (What would be even better: Add some hooks to give editor plugins the chance to alter the save format. That would make it possible to upgrade scene files and prefabs during the lifetime of a project so much easier)

    1. I think you could implement this yourself if you use OnAfterDeserialize and OnBeforeDeserialize. You would need to keep your old serialized fields around until all the data was converted but I think you could do it.

      Either that or live dangerously by forcing all your assets to text serialization and then process the text assets to your new format.

      http://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.html

      1. Yes. This is what we are doing. We encode everything into a single list of strings, which gets encoded into separate lines by YAML most of the time. The only other thing we need is a “list of objects” to hold references so Unity’s reference-system still works. Its a pain, e.g. since you cannot access even the name of any asset during OnAfterDeserialize, but relying on Unity mergability is even more pain, so…

  11. Can we expect in the future better solution for rename the fields without losing data? (automatically without user intervention). Another solution not use connections between fields and assets via inspector, instead use Resourses.Load, but this uncomfortably if you rename folders or assets in project often.

    1. Leonardo Carneiro

      February 4, 2015 at 2:19 pm

      I don’t really understand what you mean. Can you explain a bit more in detail what you would like to see?

  12. I think a “variable name” attribute could work too. So if I had a variable and I wanted to have a specific “weird” name on the inspector but not the one from the variable…
    e.g.
    public int myVar; (and the name I wanted would be “1. My Var”)

    I would go like…

    [VariableName(“1. My Var”)]
    public int myVar;

    or even on a private variable
    [VariableName(“1. My Var”)]
    [SerializeField]
    private int myVar;

    So changing the name wouldn’t lose its value reference on the inspector. It would change just the “label”.
    Of course the attribute (FormerlySerializedAs) you have created works too!

  13. I’m speaking out of some ignorance here, so apologies if this is a silly suggestion. It seems like this would be better if it somehow threw a warning on compile when developers are using a “formally serialized field”. This is similar to when a method is deprecated, is it not?

    1. Leonardo Carneiro

      February 3, 2015 at 6:07 pm

      Not really, this attribute enables developers to change field names in their code, without losing data, giving our users more flexibility to refactor their code.

  14. This is great. As a suggestion, I would say that next time it might also be worth offering a way for user to write code to modify the behavior that is affecting them. In this case maybe being able to write callback script code during the serializing/deserializing would be more useful for people, especially since it would allow people to write Asset Store utilities to solve other problems you might not have noticed.

    1. Leonardo Carneiro

      February 3, 2015 at 6:01 pm

      I think we have something very similar already. I’m not sure if it’s exactly what you want but you can get really far with: ISerializationCallbackReceiver.OnBeforeSerialize.html

      I would also recommend reading this blog post

      1. Thanks for the links!

  15. Sampsa Lehtonen

    February 3, 2015 at 4:52 pm

    Also, which Unity version is this going to be in? I hope in 4.6…

    1. It’s already in there :)

  16. Sampsa Lehtonen

    February 3, 2015 at 4:51 pm

    This is a really welcome feature. Nice job!

    In the past I’ve done something like use OnValidate to check if data has been migrated to new version, but that required keeping tabs of things – and duplicate variables. Quite awkward.

    BTW, how far can we stretch this? Would this work:

    Before:

    [System.Serializable] public class ItemA { public int value; }
    public ItemA a;

    After:

    [System.Serializable] public class ItemB { public int value; }
    [FormerlySerializedAs(“a”)]
    public ItemB b;

    that is, change the type as well where the new type is compatible with the old one. Because changing the type already works as long as the type is compatible.

    1. Leonardo Carneiro

      February 3, 2015 at 5:58 pm

      Yes, that would work just fine :)
      I guess the post is not clear on this but yeah, this is in 4.6 already!

  17. Nice.

    Just went back to my own blog post on Unity attribute (http://www.tallior.com/unity-attributes/) this seems to have been there already when I wrote it (in 4.6 RC2).

    Although the name is pretty bad to my taste :)

  18. Will something similar be done for MonoBehaviours inside assemblies?

    Right now the fileID of MonoBehaviour inside assemblies is based somewhat on MD4 of the class name, so it is not possible to refactor them.

    An attribute to set fileID explicitly would be very helpful.

    1. Emil "AngryAnt" Johansen

      February 3, 2015 at 4:56 pm

      Generally, I’d say that serialising based on assembly classes doesn’t inspire a lot of confidence.

      To the point where I would indeed not mind having to be completely explicit about it. Unfortunately that has not been an option so far.

      1. I agree that the ability to specify the a deprecated ID of a class in a dll or old name would be very useful.

    2. Agreed that this would be really useful. Not being able to rename classes inside custom-built DLLs (without losing script references in my scenes & prefabs) is currently the only big reason why I don’t use DLLs.