Modify prefab values from code – Unity3D

Problem

Generally what we would want is to modify prefab in Unity3D when they’re in an Editor (Inspector) or EditorWindow.
Yet sometimes there’s a situation like I’ve had, that we would like to set value or generally modify prefab from code and then be sure that our changes have been persisted.
You would think that simple change from code during runtime should be more then enough?
So do I!

Apparently, when I attempt to generate Guid once in a lifetime of a prefab, ie:

Unity3D sets it properly and then, resets its value after changing scene. Turning Unity Editor off and on again will also sometimes reset the values.
Surprisingly, I haven’t noticed such thing with prefabs generated inside EditorWindow scripts I wrote too.

Solution

After struggling for 2 hours in a row (that was my second attempt to fight this), I’ve managed to find a solution.
After you modify prefab in runtime, make sure to flag it with SetDirty(), it finally worked.
Of course remember, that you need to operate on prefab, not on an instance of it!

You would of course ask why I won’t make a simple button for game designers to use from inspector every time they create such MonoBehaviour. But that’s simple: it’s not error-proof. One can simple forget to push such button and it immediately becomes a debugging hell. Of course auto-generated Guid is not exposed for user for modification. I’ve edited the way it’s rendered on inspector, so that it’s only a label, not input field now.

Note

Fun part is that Unity3D team decided that in Unity3D 5.4 SetDirty() becomes obsolote:

NOTE: Prior to Unity 5.3, this was the primary method of marking objects as dirty. From 5.3 onwards, with the introduction of Multi-Scene Editing, this function should no longer be used when modifying objects in scenes. This function is due to be deprecated in future versions of Unity.

I’ve already mentioned that to my team, but if you stumble upon my post after reaching Unity3D 5.4 already, let me know if you’ve found any other way round!

uFrame MVVM and Separation of Concerns

Some of you that used to work (or work) with Unity3D might be tempted to use library called uFrame MVVM to get things seperated in proper, documented way.
As I’m currently working on a project that uses uFrame MVVM, I’d like to add few words of how and where I find uFrame MVVM actually not meeting one from many SOLID rules, that is Single Responsibility Principle and it’s a-like principle: Separation of Concerns (SoC).

About uFrame MVVM

Few words about uFrame MVVM first.
UFrame has been developed by Invert Game Studios to mimic MVVM pattern behaviour known to C# developers from WPF or ASP.NET frameworks.

Direct link to uFrame is here:

https://invertgamestudios.com/mvvm/overview

Although it’s marketed as ‘MVVM’ and it does have Views that bind to ViewModels, it resembles me more how ASP.NET MVC work with MVVM client-side, JS-based frontends.
Actually it lacks the ‘M’ (Model) part. ViewModels are used from start in a way generally models are. Logic that sometimes grows too much in WPF MVVM inside ViewModels lays in Controllers here.
I’m really delighted that finally that big-blob-VM are gone from my code and instead a true Controller taken from MVC pattern takes the responsibility.
Current way how uFrame works would be probably easier to understand with diagram I’ve prepared:

uframe mvvm seperation of concerns

Straight to the problem

Here comes the real problem though: access to instantiating views from code is accessible from Views only(!?).
I can imagine that it’s due to the fact that they’re the only ones deriving from MonoBehaviour but it strictly implies that we should use them for non-UI logic, that is validation and modification of data that should drive instantiation of Views (for ex. ModelCollection that instantiates new View based on ViewModel added to it and notified OnPropertyChanged).
Although I can understand reasons why it was designed that way (Unity3D limitations probably), I can hardly accept way of design it promotes.

My solution

My idea is to implement widely known (also from everyday life) pattern known as Producer/Consumer pattern.
We can subscribe with great reactive-programming library UniRx tool that is already used in uFrame, that is Subscribe and IObservable to ModelCollection, then we can do any business logic and validation in Controller, that is in way it’s mean to be designed.
Our next step will be pushing newly added item do InitializationContainer if it meets our business requirements/is valid etc. Then we will need an Initializer (that will be View in uFrame sense but will behave as normal MonoBehaviour for us) where T is type of ViewModel/View that we’re going to subscribe for to InitializationContainer and then consume it.
Consuming of notified View to initialize should end up in deleting the item from initialization queue in container.
We need to remember that our notification should contain both View and ViewModel, so that Initializer knows what View with what ViewModel it should instantiate.
For better understanding of an idea, here’s a next diagram:

uframe mvvm container initialization

Hope it helps anyone struggling with inconsistend seperation of concerns in uFrame MVVM! :)