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:
1 2 3 4 5 6 7 8 |
[SerializeField] private string Guid; public void Init() { if (string.IsNullOrEmpty(Guid)) Guid = Guid.NewGuid().ToString(); } |
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!
1 2 3 4 5 6 7 8 9 10 11 |
[SerializeField] private string Guid; public void Init() { if (string.IsNullOrEmpty(Guid)) { Guid = Guid.NewGuid().ToString(); EditorUtility.SetDirty(this); } } |
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!
Hmm, cannot we set guid value implicity?
The problem is that if we want to generate Guid, it would something like:
and provided that prefab is
MonoBehaviour
, standard constructor doesn’t apply here.It seems that with field initialized from hand, it sets it properly on
MonoBehaviour
script attachement toGameObject
.Problem is, that sometimes after scene changes they still tend to reevaluate the value of
private string Guid
to new value, even tough it’s a prefab that was never instantiated.