The case of the continually checked out prefabs

I’ve been helping out my friends over at Three Phase Interactive on their game Defect: Spaceship Destruction Kit a little bit. The game is being developed in Unity, and they’re using Perforce for source control. We’re using different combinations of the built-in Unity Perforce support and the P4Connect plugin. We’ve had a strange issue in Unity for a while now where it would try to check out two specific prefabs seemingly randomly. There seemed to be no reason why, as the prefabs weren’t directly being changed!

After much searching around and digging, I was able to discover the reason for this. If you have a prefab in your project with a MonoBehaviour which implements the OnValidate function, Unity will at times execute the OnValidate on prefabs that aren’t in the current scene and are not even selected in the project tab.

In the OnValidate, if you assign any values to certain members, Unity then flags the prefab as dirty, and thus when you save the project it decides that it needs to be checked out of source control. In our case the values weren’t actually changing; they were being set to the same as their initial values, so the prefabs would be checked out but then there wouldn’t be any changes in the file.

The most common times when Unity runs OnValidate appear to be when entering play mode, and when Unity rebuilds after code has changed.

I was able to reproduce this behaviour in a small test project, but only when modifying properties of the GameObject‘s transform (e.g. setting transform.rotation to identity). Setting serialised class members didn’t seem to trigger this issue, so it seems that it only happens if you set built-in Unity properties (maybe it hooks into the property setter).

In SDK the way I solved this was to add this code to the top of the OnValidate methods:

#if UNITY_EDITOR
   if (gameObject.hideFlags == HideFlags.HideInHierarchy)
      return;
#endif

However in my test project, that didn’t work, and I had to instead do this:

if (transform.rotation != Quaternion.identity)
   transform.rotation = Quaternion.identity;

I suspect that only changing the values if they are different is the more reliable method; in SDK prefabs seemed to be set to HideInHierarchy but that wasn’t the case in my test project. I’m not sure why as I couldn’t see anywhere where it was changing the hide flags, so I may have to go back and change it in SDK.

It took a while to figure this out, but it was thanks to a post over on the NGUI forums here and a post on Unity answers here that I was able to track this down!

2 Responses to “The case of the continually checked out prefabs”

  1. Aubrey Hesselgren on Reply

    God bless you. Was tearing my hair out about this. It feels extremely ugly to check that a change will occur before using the OnValidate, but, hey, the endless if statements did actually work for me, so thanks. (We’re using perforce, but I’ve heard there’s a similar issue with subversion/SVN)

    • Sam on Reply

      No problem! I definitely feel your frustration – I was tearing my hair out when trying to figure this out too. It was so frustrating!

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current day month ye@r *