Any plans to update/replace the SerializedObject/Property system?

I know I’ve brought this up in threads before, but now’s the best time to put it to the devs.

I can’t be the only one to think that the SerializedObject/Property system is no longer fit for purpose. It’s what, nearly a decade old if not older? Not to mention written in a way that is clearly antiquated by current coding styles/standards.

We can’t even get the underlying value as a System.Type without going through the .boxedValue property (Which only became available in 2022.1!). The type of the value is instead an enum!!! SerializedProperty also combines both the API for the structure of the data with the the actual data, when these should be separate.

Multiple times I’ve been working on a tool initially for myself that I would’ve liked to release either paid or free, but dealing with this old system became too cumbersome that I just used Odin Inspector’s replacement system instead (known as the PropertyTree) because it saves me tons of effort. Thus I can’t really release them without stipulating Odin as a requirement.

I also feel like it’s been holding Unity’s own editor tooling back, as if us general users are having these issues then they must be too!

Anything closer towards Odin’s PropertyTree/InspectorProperty system would be a massive upgrade for both us and for Unity’s own devs too.

4 Likes

I can’t be the only one to think that the SerializedObject/Property system is no longer fit for purpose. It’s what, nearly a decade old if not older?

Fit for the purpose or not, replacing SerializedObject and SerializedProperty is something that would be extremely disruptive, as so many editor tools and workflows rely on it. If it was only used internally, I could make a case to replace it, but I believe it’s used too much to replace. At best, we would get an alternative system that would sit alongside it for many years.

I think updating it would make sense.

Not to mention written in a way that is clearly antiquated by current coding styles/standards.

We have made some improvements on that front and will continue to do so. For example, for the editor inspector bindings, we want to remove the Update call on the bindings and migrate towards manually updating the bindings when a change has actually occurred. There are ways to modernize it without rewriting it all from scratch, if only by adding a layer on top of the current APIs to make it easier to work with.

1 Like

I have also really been feeling the pain of SerializedProperties/SerializedObjects over the years. I really agree that improving the API is a much better plan that replacing it - Unity has done too much replacing and too little improving over the years.

Here’s brief list of things that are wrong and I think you need to improve on;

  • DeleteArrayElementAtIndex has completely different behaviour depending on if the referenced object is a UnityEngine.Object or if it’s any other type of value. So any helper code you write that tries to remove things from arrays have to have two code paths. This is also not documented anywhere!

  • Sorting arrays is very clunky. Since SerializedProperty isn’t an IList or anything like that, we have to manually implement a sort function instead of just calling Array.Sort or List.Sort or whatever. And how SerializedProperty.MoveElement works (remove, insert) is not actually documented in words, you just have to look at the example code and intuit it.

  • There’s no type safety anywhere. Being able to get a SerializedProperty<float> instead of having to interact with an untyped SerializedProperty and checking if it’s a SerializedPropertyType.Float and getting the .floatValue would do wonders for code readability and safety.

  • You can’t insert a non-initialized element into a SerializedProperty array. Every time you want to add something, what gets added is a copy of the object in the slot before it. This makes working with arrays of complex [Serializable] classes a nightmare, as you have to go through the entire SerializedProperty tree of the newly created object and set up the values. The documentation claims that the value is undefined, which is nonsense.

  • Binding to array elements is also very bad and unintuitive, since you’re binding to an array index, so if you modify how many elements there are in the array you modify what everything you have bound is pointing at. It’s very easy to introduce bugs if you’re not super carefull here - and this became a much bigger problem in uitk since it’s a retain mode UI framework and you don’t just redo the entire UI every frame. This one is probably not fixable, but somebody might have better ideas than me.

  • The SerializedProperty iterator is crazy. The implementation where each object is also an iterator that modifies the object itself is perhaps the strangest implementation choice I have seen of anything anywhere. I have never met any programmer that thinks they’re able to write a SerializedProperty iterator correctly on the first try from scratch. It’s always either a copy-paste or a trial and error process.

2 Likes

I agree with all of those issues and for the most part, changing those behaviours would create a ton of regressions, so we might end up creating a layer on top of it that’s easier to work with, while keeping existing code working the same way it used to.

In my spare time (read this as 100% unofficial), I’ve toyed around using the Properties module to wrap the SerializedObject/SerializedProperty APIs and offer a type-safe API instead, which would be compatible with the visitation patterns that the module offers. It still needed a lot of work to abstract everything, but it was very promising.

3 Likes

In the same vein that UI Toolkit and IMGUI can coexist, so could a replacement SerializedObject system exist with the old system.

Eg: an UnityEditor.Editor could express both a .serializedObject and a property for whatever the new object would be called. Then new Inspectors and editor tools can be built on the new system without affecting olds ones, which can be ported over in their own time.

Yes, we made UI Toolkit and IMGUI coexist and it was extremely disruptive. It still is today to some degree. So it’s not that we can’t do it, it’s what’s the cost and for how long? What features are we willing to delay or cancel to rewrite the inspector and, by extension, a lot of the extensibility framework? How many years will we have to maintain two systems in parallel and will we ever be able to remove the previous one without causing incredible friction?

We can still make things better working in layers instead of starting another stack on the side.

2 Likes

I feel like certain parts of Unity being built on old tech has been worse off in the long term than if a new tech stack was made. Look at Addressables, which is built on Asset Bundles. It doesn’t fix the inherent limitations of Asset Bundles; it just makes a janky old API slightly less jank to use. At this point if a whole new system was made, we would be leagues ahead of where we are now.

So if I may come from the opposite direction, would a wrapper system be able to solve the inherent limitations that we have with SerializedObject? Or would a lot of time just be spent on it to leave us at a slightly less inconvenient dead end?

For example, limitations such as not being able to make a serialized object out a non-UnityEngine.Object asset, or automatic drawing of non-serialized fields? These are probably the two most egregious limitations of the old system that come to mind. Next most painful is not being able to declare a drawer for a collection, or the lack luster type matching for drawers as well (though I don’t think this is directly a result of the SerializedObject system).

And I understand I made the UI Toolkit/IMGUI comparison but I don’t think a new SerializedObject system would be that disruptive in the long run. Same as how the Odin PropertyTree exists fine within Unity as well. It’s a different API that other systems can opt to use (In Odin’s case, pay to use).

On that note, I do have to ask if you have used Odin? Namely, written an Odin drawer, using the property tree, and seen how much more convenient and powerful it is? If not, I suggest playing around with it to see where I’m coming from. There’s so many things that are impossible or incredibly difficult to do with Unity that are effortless with Odin. It’s crazy how far behind the SerializedObject system is.

EDIT: Though to be clear I would see an update to the existing system, even a wrapper system, to be a huge step up. I just wanted to advocate for a replacement system, as for all intents and purposes, there technically is one, and the divide between it and the SerializedObject system is wider than the Valles Marineris.

I feel like certain parts of Unity being built on old tech has been worse off in the long term than if a new tech stack was made.

We are definitely in agreement about that, but it’s hard to judge that before the work is completed. Sometimes you rewrite from scratch and you end up with a system that fixes the original jank, but introduces another class of jankiness.

And obviously, I’m coming at this problem from a UI perspective, where SerializedObject/SerializedProperty is but a small part of what we use in our own tech stack. I would definitely welcome any improvements on the base layers, and we try to make some whenever possible. It is however, far from my area of expertise and I’d prefer to stay focused on UI.

We did decide to start completely from scratch when we implemented the runtime bindings instead of enhancing the editor bindings and, in hindsight, I think that was a very good decision. I was able to convince all stakeholders that it was the right decision, which is much easier when the existing solution is more or less a black box. I doubt I would be able to do the same for rewriting a base layer of Unity.

For example, limitations such as not being able to make a serialized object out a non-UnityEngine.Object asset, or automatic drawing of non-serialized fields? These are probably the two most egregious limitations of the old system that come to mind.

Yes, and that is because the inspector framework and overall editor workflows is directly seated on top of the serialization. I would much prefer if the two were separate, but there again, it’s a huge undertaking.

Next most painful is not being able to declare a drawer for a collection[…]

Good news, you should now be able to using PropertyAttribute.applyToCollection.

On that note, I do have to ask if you have used Odin?

I used to when I was working on games. It’s a great plugin! And unironically, Odin existing, and being a verified solution, probably makes it harder to convince everyone that we should stop doing x and y feature to do this refactor.

And I understand I made the UI Toolkit/IMGUI comparison but I don’t think a new SerializedObject system would be that disruptive in the long run.

That depends on what you want to get out of that new system. If it’s only a better API on top of the serialized data, than yeah, it might not be too much. But if you want to display non-serialized fields and properties while still retaining undo/redo during edition, then it’s already a lot more complicated and we would need to change a lot more things than SerializedObject/SerializedProperty.

Honestly, I agree with most of your points and I’d love to see it happen. That being said, our list of priorities is not short. :slight_smile:

1 Like

Awesome! This alone might allow me to (potentially) remove Odin as a dependency from some of my tools. At least for Unity 6 users, that is.

Internally I’m still always going to use Odin.

Honestly my wish-list would be a clear separation between these four layers:

  1. Top most layer that handles drawing
  2. Second most layer for the structure of the data
  3. Third layer for the underlying values of said data
  4. Fourth layer for the underlying serialization of said data

I think having those four separate would probably allow for nearly every feature we could want to be added in some capacity.

I can imagine! And thanks for listening and for the chance to make my case directly.

I can imagine! And thanks for listening and for the chance to make my case directly.

It’s absolutely my pleasure.

As someone who co-wrote the Properties module, wrote the Properties.UI package and helped on the Serialization package, these subjects are very dear to me. They were an attempt at fixing those issues by creating a property bag that is separate from UI or serialization and each could play with the property bag in different ways.

And this is in part why I think it can become quite disruptive, because using those, we can get pretty far along the path, but oftentimes when you get further down the path, you realize that what you thought was the destination is in fact the first stop, the classic 80%-20%, where the 20% takes 80% of the time.

1 Like