Asset Change Detection¶
Automatically respond to asset creation and deletion events.
The [DetectAssetChanged] attribute allows you to annotate methods that should execute automatically when specific asset types are created or deleted in the Unity Editor. Perfect for cache invalidation, autoconfiguration, validation, and maintaining derived data.
Table of Contents¶
- Basic Usage
- Attribute Parameters
- Method Signatures
- Inheritance Support
- Asset Change Context
- Best Practices
- Examples
Basic Usage¶
Visual Reference
Automatic method invocation when assets are created or deleted
Attribute Parameters¶
| C# | |
|---|---|
AssetChangeFlags¶
| C# | |
|---|---|
DetectAssetChangedOptions¶
| C# | |
|---|---|
Important:
SearchPrefabsandSearchSceneObjectsare only applicable to instance methods on MonoBehaviour classes. Static methods work without these options.
Method Signatures¶
The attribute supports three method signatures:
1. No Parameters (Fire-and-Forget)¶
| C# | |
|---|---|
When to use: Simple cache invalidation that doesn't need asset details
2. Full Context (Recommended)¶
When to use: Need to handle both creation and deletion, or need access to all changed paths
3. Typed Arrays (Advanced)¶
When to use: Need strongly-typed access to created assets; deleted assets are always paths since the asset no longer exists
Inheritance Support¶
By default, the attribute only triggers for exact type matches. Use IncludeAssignableTypes to include derived types:
Asset Change Context¶
The AssetChangeContext class provides complete information about the change:
Best Practices¶
Performance Considerations¶
- Keep methods fast - They run synchronously during asset import
- Avoid heavy operations - Consider deferring work with
EditorApplication.delayCall - Use static methods when possible - Faster invocation, no instance required
Design Patterns¶
Avoiding Reentrant Issues¶
Examples¶
Cache Invalidation¶
| C# | |
|---|---|
Auto-Configuration¶
Derived Type Monitoring¶
Prefab-Based Instance Methods¶
Use SearchPrefabs to invoke instance methods on MonoBehaviours attached to prefabs:
When to use: When your MonoBehaviour needs instance-specific state or serialized fields
Scene Object Instance Methods¶
Use SearchSceneObjects to invoke instance methods on MonoBehaviours in open scenes:
When to use: For editor tools that need to react to changes based on scene-specific configuration
Combined Prefab and Scene Search¶
Use both options together to find handlers in both prefabs and open scenes:
Performance Note: Searching prefabs and scenes has overhead. Use these options only when you need instance-specific behavior. For simple notifications, prefer static methods.
Callback scheduling¶
The watcher discovers methods marked [DetectAssetChanged] and dispatches matching asset changes on the Editor's main thread. Keep callbacks short. Importing or modifying assets from a callback can queue another change batch; repeated cycles can activate loop protection.
When the Watcher Runs¶
| Context | Default behavior |
|---|---|
| Interactive Editor | The watcher initializes automatically. |
| Play mode or a transition into it | Asset-import notifications are ignored. |
Batch mode (-batchmode, CI, headless) | Initialization is disabled unless explicitly enabled. |
Choose an initialization policy from an [InitializeOnLoad] static constructor, before the watcher's deferred initialization. This example disables automatic initialization in an interactive Editor:
| C# | |
|---|---|
Set Enabled = true instead when a headless asset pipeline needs the watcher. Call ResetEnabledToDefault() to remove your override. Set the policy before initialization: it is not a switch that removes subscriptions already discovered in the current domain.
Turning the watcher off after it has already initialized stops further initialization but leaves already-discovered subscriptions in place.
For a temporary change, use the scope instead of assigning and restoring by hand; it captures the current state on construction and puts it back on dispose, so an early return or an exception cannot leak the override:
Troubleshooting¶
Method Is Not Called¶
- Ensure the method is in a type that Unity can discover (not in a generic class)
- Check that the asset type matches exactly (unless using
IncludeAssignableTypes) - Verify the asset change flags match the operation (Created vs. Deleted)
- For MonoBehaviour instance methods:
- Use
SearchPrefabsif the handler is on a prefab asset - Use
SearchSceneObjectsif the handler is on a GameObject in a scene - Instance methods without these options only work for ScriptableObjects saved as assets
A Watcher Does Not Fire for a Prefab¶
A prefab is matched by the type of its main asset, which Unity reports as GameObject. It is never opened to see what it contains, so a watcher on some other type will not fire for it, and neither will a watcher on the type of a sub-asset nested into a .prefab. (Nested sub-assets in .asset files are matched normally.)
For other asset files, matching a sub-asset uses Unity's type index. The watcher checks the imported path without loading every object in the file, so unrelated imports do not deserialize components just to test their types. Sprite sub-assets of textures and nested ScriptableObjects remain discoverable.
That is deliberate. Opening a prefab deserializes every component in it, which runs each one's OnValidate, so your own code runs, on every prefab, on every import, and Unity logs SendMessage cannot be called during Awake, CheckConsistency, or OnValidate for any OnValidate that touches an API it relays. Watching a prefab by what it contains is not supported; watch a GameObject and inspect the prefab yourself if you need it.
SearchPrefabs is a different feature and does not change this: it searches prefabs for instances of the handler's own type, so that a non-static [DetectAssetChanged] method can be invoked on them. It has no effect on which assets match a watcher.
MonoBehaviour Instance Methods Not Working¶
If your instance method on a MonoBehaviour isn't being called:
- On a prefab? Add
DetectAssetChangedOptions.SearchPrefabs - In a scene? Add
DetectAssetChangedOptions.SearchSceneObjects - Need both? Combine:
SearchPrefabs | SearchSceneObjects - Don't need instance state? Use a
staticmethod instead (most efficient)
Performance Issues¶
Watcher initialization uses Unity's type cache to find annotated methods. Profile asset matching and callback work if imports remain slow.
- Profile with Unity Profiler during asset import
- Consider deferring work with
EditorApplication.delayCall - Use
staticmethods to avoid unnecessary instance lookups - Avoid
SearchPrefabsin large projects - it loads all prefabs to check for components - Avoid
SearchSceneObjectswith many open scenes - searches all loaded scenes
Resetting Loop Protection¶
If a callback repeatedly creates more matching asset changes, the watcher enters loop protection and skips additional batches until it is reset. After fixing the callback or clearing the bad state, editor tools can resume dispatch without a domain reload:
| C# | |
|---|---|
The reset clears only loop-protection state and queued changes. It preserves discovered watchers and subscriptions.
Null Reference Exceptions¶
- Remember: asset parameter is
nullfor deletion events - Always null-check when handling
AssetChangeFlags.Deleted
Related Features¶
- Attribute Metadata Cache Generator - Caches attribute metadata for fast lookup
- ScriptableObject Singleton Creator - Auto-creates singleton assets
- Inspector Attributes - Other custom inspector features
Automatic method invocation when assets are created or deleted