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.
[DetectAssetChanged( Type assetType, // Type of asset to monitor (required) AssetChangeFlags flags, // Created, Deleted, or both (required) DetectAssetChangedOptions options = None // IncludeAssignableTypes for inheritance)]
[Flags]publicenumDetectAssetChangedOptions{None=0,IncludeAssignableTypes=1<<0,// Also trigger for derived typesSearchPrefabs=1<<1,// Search prefabs for MonoBehaviour handlersSearchSceneObjects=1<<2,// Search open scenes for MonoBehaviour handlers}
Important:SearchPrefabs and SearchSceneObjects are only applicable to instance methods on MonoBehaviour classes. Static methods work without these options.
[DetectAssetChanged(typeof(ScriptableObject), AssetChangeFlags.Created)]privatestaticvoidOnScriptableObjectCreated(){Debug.Log("A ScriptableObject was created - invalidate cache");}
When to use: Simple cache invalidation that doesn't need asset details
// Triggers for ScriptableObject and ALL derived types[DetectAssetChanged( typeof(ScriptableObject), AssetChangeFlags.Created, DetectAssetChangedOptions.IncludeAssignableTypes)]privatestaticvoidOnAnyScriptableObjectCreated(ScriptableObjectobj){Debug.Log($"ScriptableObject created: {obj.GetType().Name}");}// Only triggers for exact Material type (not derived classes)[DetectAssetChanged(typeof(Material), AssetChangeFlags.Created)]privatestaticvoidOnExactMaterialCreated(Materialmat){Debug.Log("Material (exact type) created");}
publicsealedclassAssetChangeContext{publicTypeAssetType{get;}// The type being watchedpublicAssetChangeFlagsFlags{get;}// Created, Deleted, or bothpublicIReadOnlyList<string>CreatedAssetPaths{get;}// Paths of created assetspublicIReadOnlyList<string>DeletedAssetPaths{get;}// Paths of deleted assetspublicboolHasCreatedAssets{get;}// True if any createdpublicboolHasDeletedAssets{get;}// True if any deleted}
publicclassSpriteCache:MonoBehaviour{[SerializeField]privateList<Sprite>_cachedSprites=new();[DetectAssetChanged( typeof(Sprite), AssetChangeFlags.Created | AssetChangeFlags.Deleted, DetectAssetChangedOptions.SearchPrefabs )]privatevoidOnSpriteChanged(AssetChangeContextcontext){// This instance method is called on the prefab assetDebug.Log($"SpriteCache on prefab received sprite change: {context.Flags}");RefreshCache();}privatevoidRefreshCache(){_cachedSprites.Clear();// Rebuild cache...}}
When to use: When your MonoBehaviour needs instance-specific state or serialized fields
publicclassLiveAssetWatcher:MonoBehaviour{[SerializeField]privatestring_watchedFolder;[DetectAssetChanged( typeof(Texture2D), AssetChangeFlags.Created, DetectAssetChangedOptions.SearchSceneObjects )]privatevoidOnTextureCreated(AssetChangeContextcontext){// Called on every LiveAssetWatcher instance in all open scenesforeach(stringpathincontext.CreatedAssetPaths){if(path.StartsWith(_watchedFolder)){Debug.Log($"{name} detected new texture: {path}");HandleNewTexture(path);}}}privatevoidHandleNewTexture(stringpath){/* ... */}}
When to use: For editor tools that need to react to changes based on scene-specific configuration
publicclassUniversalAssetHandler:MonoBehaviour{[DetectAssetChanged( typeof(AudioClip), AssetChangeFlags.Created | AssetChangeFlags.Deleted, DetectAssetChangedOptions.SearchPrefabs | DetectAssetChangedOptions.SearchSceneObjects )]privatevoidOnAudioClipChanged(AssetChangeContextcontext){// Called on instances in both prefabs AND scene objectsDebug.Log($"{name} (on {gameObject.name}) received audio change");}}
Performance Note: Searching prefabs and scenes has overhead. Use these options only when you need instance-specific behavior. For simple notifications, prefer static methods.