Index: Private/NoesisRuntimeModule.cpp
===================================================================
--- Private/NoesisRuntimeModule.cpp	(revision 16791)
+++ Private/NoesisRuntimeModule.cpp	(working copy)
@@ -308,6 +308,16 @@
 	NoesisDestroyTypeClassForBlueprint(Blueprint);
 }
 
+void OnAssetsAdded(TConstArrayView<FAssetData> Assets)
+{
+	NoesisRegisterMaterials(Assets);
+}
+
+void OnAssetsRemoved(TConstArrayView<FAssetData> Assets)
+{
+	NoesisUnregisterMaterials(Assets);
+}
+
 void OnAssetRenamed(const FAssetData& AssetData, const FString& OldPath)
 {
 	UObject* NewObject = AssetData.GetAsset();
@@ -973,6 +983,8 @@
 
 			FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
 			IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
+			AssetsAddedHandle = AssetRegistry.OnAssetsAdded().AddStatic(&OnAssetsAdded);
+			AssetsRemovedHandle = AssetRegistry.OnAssetsRemoved().AddStatic(&OnAssetsRemoved);
 			AssetRenamedHandle = AssetRegistry.OnAssetRenamed().AddStatic(&OnAssetRenamed);
 		}
 #endif
@@ -1009,6 +1021,8 @@
 		{
 			FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
 			IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
+			AssetRegistry.OnAssetsAdded().Remove(AssetsAddedHandle);
+			AssetRegistry.OnAssetsRemoved().Remove(AssetsRemovedHandle);
 			AssetRegistry.OnAssetRenamed().Remove(AssetRenamedHandle);
 
 			FEnumEditorUtils::FEnumEditorManager::Get().RemoveListener(NotifyEnumChangedListener);
@@ -1115,6 +1129,8 @@
 	FDelegateHandle BlueprintPreCompileHandle;
 	NotifyEnumChanged* NotifyEnumChangedListener;
 	NotifyStructChanged* NotifyStructChangedListener;
+	FDelegateHandle AssetsAddedHandle;
+	FDelegateHandle AssetsRemovedHandle;
 	FDelegateHandle AssetRenamedHandle;
 #endif
 	TSharedPtr<class IInputProcessor> InputPreProcessor;
Index: Private/NoesisTypeClass.cpp
===================================================================
--- Private/NoesisTypeClass.cpp	(revision 16791)
+++ Private/NoesisTypeClass.cpp	(working copy)
@@ -68,6 +68,7 @@
 #include "NoesisSDK.h"
 
 #ifdef WITH_EDITOR
+    #include "Interfaces/IPluginManager.h"
     #include "NoesisSettings.h"
 #endif
 
@@ -3804,6 +3805,109 @@
 	OnMaterialChanged(Material);
 }
 
+static void GetProjectPaths(TArray<FString>& ProjectPaths)
+{
+	ProjectPaths.Add(TEXT("/Game"));
+
+	TArray<TSharedRef<IPlugin>> EnabledPlugins = IPluginManager::Get().GetEnabledPlugins();
+	for (const TSharedRef<IPlugin>& Plugin : EnabledPlugins)
+	{
+		if (Plugin->GetLoadedFrom() == EPluginLoadedFrom::Project)
+		{
+			ProjectPaths.Add(*Plugin->GetMountedAssetPath().LeftChop(1));
+		}
+	}
+}
+
+static bool IsProjectAsset(const FAssetData& AssetData, const TArray<FString>& ProjectPaths)
+{
+	bool Found = false;
+
+	FString Path = AssetData.PackagePath.ToString();
+	for (const FString& ProjectPath : ProjectPaths)
+	{
+		if (Path.StartsWith(ProjectPath))
+		{
+			Found = true;
+			break;
+		}
+	}
+
+	return Found;
+}
+
+void NoesisRegisterMaterials(TConstArrayView<FAssetData> Assets)
+{
+	Noesis::Studio::ClearTypeCache();
+
+	TArray<FString> ProjectPaths;
+	GetProjectPaths(ProjectPaths);
+
+	for (const FAssetData& AssetData : Assets)
+	{
+		if (AssetData.IsInstanceOf(UMaterialInterface::StaticClass()) &&
+			IsProjectAsset(AssetData, ProjectPaths))
+		{
+			if (UMaterialInterface* Material = Cast<UMaterialInterface>(AssetData.GetAsset()))
+			{
+				if (UMaterial* BaseMaterial = Material->GetBaseMaterial())
+				{
+					if (BaseMaterial->MaterialDomain == MD_UI ||
+						BaseMaterial->MaterialDomain == MD_PostProcess)
+					{
+						NoesisTypeClass** TypeClassPtr = MaterialMap.Find(Material);
+						if (TypeClassPtr == nullptr)
+						{
+							Noesis::TypeClass* Type = NoesisCreateTypeClassForUMaterial(Material);
+							Noesis::Reflection::RegisterType(Type);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	Noesis::Studio::PopulateTypeCache();
+}
+
+void NoesisUnregisterMaterials(TConstArrayView<FAssetData> Assets)
+{
+	Noesis::Studio::ClearTypeCache();
+
+	TArray<FString> ProjectPaths;
+	GetProjectPaths(ProjectPaths);
+
+	for (const FAssetData& AssetData : Assets)
+	{
+		if (AssetData.IsInstanceOf(UMaterialInterface::StaticClass()) &&
+			IsProjectAsset(AssetData, ProjectPaths))
+		{
+			if (UMaterialInterface* Material = Cast<UMaterialInterface>(AssetData.GetAsset()))
+			{
+				if (UMaterial* BaseMaterial = Material->GetBaseMaterial())
+				{
+					if (BaseMaterial->MaterialDomain == MD_UI ||
+						BaseMaterial->MaterialDomain == MD_PostProcess)
+					{
+						NoesisTypeClass** TypeClassPtr = MaterialMap.Find(Material);
+						if (TypeClassPtr != nullptr)
+						{
+							NoesisTypeClass* TypeClass = *TypeClassPtr;
+							bool IsRegistered = IsTypeRegistered(TypeClass);
+							if (IsRegistered)
+							{
+								Noesis::Reflection::UnregisterNoDelete(TypeClass);
+								MaterialMap.Remove(Material);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	Noesis::Studio::PopulateTypeCache();
+}
 void NoesisAssetRenamed(UObject* Object, FString OldPath)
 {
 	Noesis::Studio::ClearTypeCache();
@@ -3865,6 +3969,22 @@
 			}
 		}
 	}
+	else if (UMaterialInterface* Material = Cast<UMaterialInterface>(Object))
+	{
+		NoesisTypeClass** TypeClassPtr = MaterialMap.Find(Material);
+		if (TypeClassPtr != nullptr)
+		{
+			NoesisTypeClass* TypeClass = *TypeClassPtr;
+			bool IsRegistered = IsTypeRegistered(TypeClass);
+			if (IsRegistered)
+			{
+				Noesis::Reflection::UnregisterNoDelete(TypeClass);
+				MaterialMap.Remove(Material);
+			}
+			Noesis::TypeClass* Type = NoesisCreateTypeClassForUMaterial(Material);
+			Noesis::Reflection::RegisterType(Type);
+		}
+	}
 	Noesis::Studio::PopulateTypeCache();
 }
 #endif
Index: Public/NoesisTypeClass.h
===================================================================
--- Public/NoesisTypeClass.h	(revision 16791)
+++ Public/NoesisTypeClass.h	(working copy)
@@ -135,6 +135,8 @@
 NOESISRUNTIME_API void NoesisDestroyTypeClassForStruct(class UUserDefinedStruct*);
 NOESISRUNTIME_API void NoesisDestroyTypeClassForEnum(class UEnum*);
 NOESISRUNTIME_API void NoesisDestroyTypeClassForMaterial(class UMaterialInterface*);
+NOESISRUNTIME_API void NoesisRegisterMaterials(TConstArrayView<FAssetData> Assets);
+NOESISRUNTIME_API void NoesisUnregisterMaterials(TConstArrayView<FAssetData> Assets);
 NOESISRUNTIME_API void NoesisAssetRenamed(UObject* Object, FString OldPath);
 #endif
 
