Calling AssetDatabase.Refresh() - mandatory reading or face the consequences!

Failure to comply to these instructions will lead to your Unity Developer License being revoked for life. :smile::stuck_out_tongue:

Seriously, it’s been bothering me for many years that AssetDatabase.Refresh() is being indiscriminately used everywhere everytime anything even remotely related to the asset pipeline is being called … just because it can’t hurt, right?

Well yes, it can! Read on … and learn why you’ve been calling it way too often!

The AssetDatabase.Refresh() FAQ
Everything You Always Wanted to Know About Refresh()*
(*But Didn’t Bother to Ask)

What is AssetDatabase.Refresh() - really?

It is ONLY needed when asset changes were made BYPASSING the AssetDatabase entirely!

By calling Refresh() in such cases, Unity will check for such changes and integrate them into the AssetDatabase, triggering Asset Importers where necessary.

If, however, all changes were made via AssetDatabase methods to begin with, the AssetDatabase already knows about these changes! It really needn’t check the entirety of the Assets file system tree for changes nor call Resource.UnloadUnusedAssets() internally afterwards.

When to call Refresh()?

  • CALL: after using System.IO methods, eg Directory.CreateDirectory(), File.WriteAllText(), etc operating within the /Assets tree (except for /Assets/StreamingAssets)
  • CALL: after running an external program or script modifying /Assets contents without Unity editor losing focus at the same time (Editor regaining focus triggers an auto-refresh)
  • CALL: after using a code snippet/framework that wasn’t written specifically for Unity and which modifies contents in the /Assets tree

What happens when you didn’t call Refresh() when you should have?

The common issues of what happens in such a case are fairly obvious once you’re aware of them:

  • A directory or file you created / deleted / moved / renamed is not correctly listed in the Project explorer view (missing or still there)
  • Calls to the AssetDatabase (such as Find, Load, Import) with the new asset path fail or return null
  • A file whose contents were modified does not trigger the asset importer, which results in these changes not being reflected in the Editor - Note: in such cases you would simply call Import(), not Refresh()!

There may be other reasons for Auto-Refresh not working as expected. In such cases investigate the following:

  • Preferences => Asset Pipeline => Auto Refresh disabled?
  • DisallowAutoRefresh() not followed by and equal number of AllowAutoRefresh() calls?
  • StartAssetEditing() not followed by an equal number of StopAssetEditing() calls?
  • Exception raised in the latter two cases where these method pairs were not properly enclosed within a try{Disallow/Start} finally{Allow/Stop} block?

When NOT to call Refresh()?

  • DON’T CALL: after modifying assets solely via calls to AssetDatabase (Create/Copy/Delete/Extract/Import/Load/Move/Rename/Save)
  • DON’T CALL: after modifying asset contents solely via calls to AssetDatabase (AddObject/ClearLabels/SetLabels/SetMainObject/…)
  • DON’T CALL: after calls to Start/StopAssetEditing and Disallow/AllowAutoRefresh (unless changes were made bypassing the AssetDatabase in between)
  • DON’T CALL: there’s probably more … feel free to post your example use case for analysis :wink:

Why not just call Refresh() anyway - it can’t hurt, right?

  • Possible loss of data! Assets referenced only by scripts are unloaded. If such an asset was modified but not flagged as “dirty” those changes are lost after Refresh()! We’ve probably all experienced these at some point but never attributed them to Refresh().
  • It’s a code smell, and is a bad habit all around the Unity community. It’s needlessly consuming time and resources to call Refresh() indiscriminately. It runs an asset garbage collection cycle, unloading unused assets, which may slow down the editor (worst case: a continuous unload/reload cycle).

Thanks for reading!

Your Unity license should be save … for now. I’ll be watching. :sunglasses:

13 Likes

Feel free to suggest corrections / amendments. For me too the AssetDatabase is a black box. The above is what I’ve learned over the years trying to decipher the mysteriously garbled voices this black box is emitting.

I wonder if Unity should do a pass looking at methods like Refresh ( and I’m sure there will be others ) to see if any of them might benefit from having a delayed/deferred activation like behaviour overloaded method. The idea being to move methods and actions such as this from immediately updating the asset database to one where the asset database is only updated at the end of an editor frame.

Obviously there are valid cases where an asset/script would need to call the current refresh method as it might need to act on the newly added assets, but in many cases its just as likely deferring the update to the end of the editor frame would be sufficient.

I guess maybe Refresh isn’t as likely as other methods ( none come to mind, but I’m sure I’ve come across some in the past whilst writing a script ) to be called that frequently in the same frame by many different scripts, but the overall point still stands. I just feel that as you start using more and more third party assets/scripts in a project there are editor methods that can be called frequently in the same frame that could just be queued up and ran once instead.

1 Like

I needed to read this about 8 years ago, when I started using Unity.
Thanks for the great write-up and clear explanations. Hopefully others will find this and be helped out too.
:slight_smile:

2 Likes