I am consistently getting materials that use a autodeks interactive shader and they do not convert to a lit HDRP material. This is so consistent with asset store materials that I’m not sure why Unity has not fixed this as a quality of life thing for developing. When switching manually to HDRP Lit it wipes all textures out of their slots.
I had the same problem so I wrote this script to convert materials to HDRP. It works with Autodesk Interactive materials, but can easily be extended to support other materials as well.
using System;
using UnityEditor;
using UnityEngine;
using static UnityEditor.ShaderGraph.Internal.KeywordDependentCollection;
public class MaterialToHDRP : MonoBehaviour
{
[MenuItem("Tools/Convert selected Materials to HDRP...", priority = 0)]
private static void upgradeSelected()
{
foreach(string guid in Selection.assetGUIDs)
{
string assetPath= AssetDatabase.GUIDToAssetPath(guid);
Material m=AssetDatabase.LoadAssetAtPath<Material>(assetPath);
Material mInstance=Instantiate(AssetDatabase.LoadAssetAtPath<Material>(assetPath));
mInstance.name = m.name;
if (convert(mInstance))
EditorUtility.CopySerialized(mInstance, m); //Makes sure we keep the original GUID
}
AssetDatabase.SaveAssets();
}
private static bool convert(Material m)
{
string shaderName= m.shader.name;
if (shaderName.Equals("Autodesk Interactive",StringComparison.OrdinalIgnoreCase))
{
//Read
Texture albedo = m.GetTexture("_MainTex");
Texture metallic = m.GetTexture("_MetallicGlossMap");
Texture roughness = m.GetTexture("_SpecGlossMap");
Texture normal = m.GetTexture("_BumpMap");
float bumpScale = m.GetFloat("_BumpScale");
Vector2 offset = m.mainTextureOffset;
Vector2 tiling = m.mainTextureScale;
//Convert
m.shader= Shader.Find("HDRP/Lit");
m.SetTexture("_BaseColorMap", albedo);
m.SetTexture("_NormalMap", normal);
m.SetFloat("_NormalScale", bumpScale);
m.mainTextureOffset = offset;
m.mainTextureScale = tiling;
return true;
}
return false;
}
}
Note that it does not copy all the material parameters, but can be extended for more detailed conversion. However, some of the maps cannot be used in the Lit shader directly anyway, as the autodesk interactive material have separate slots for roughness and metallic for example, while the Lit shader has combined multiple masks into one using the RGB components, which helps save memory.
For a perfect conversion you’d need to make a shadergraph shader that takes the same input as the Autodesk Interactive shader, and then use the above script to convert to that new shader.
Hope it is helpful for someone ![]()
Here is an improvement on that, this will also make a mask and assign it:
// Assets/Editor/AutodeskToHDRPConverter.cs
#if UNITY_EDITOR
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
public static class AutodeskToHDRPConverter
{
[MenuItem("Tools/Convert selected Materials to HDRP…", priority = 0)]
private static void UpgradeSelected()
{
var guids = Selection.assetGUIDs;
if (guids == null || guids.Length == 0) return;
try
{
for (int i = 0; i < guids.Length; i++)
{
string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]);
var src = AssetDatabase.LoadAssetAtPath<Material>(assetPath);
if (src == null) continue;
EditorUtility.DisplayProgressBar("HDRP Material Upgrade", src.name, (float)i / guids.Length);
UpgradeOne(src, assetPath);
}
}
finally
{
EditorUtility.ClearProgressBar();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}
private static void UpgradeOne(Material src, string assetPath)
{
// Only touch Autodesk Interactive
var shaderName = src.shader != null ? src.shader.name : string.Empty;
if (!shaderName.Equals("Autodesk Interactive", StringComparison.OrdinalIgnoreCase))
return;
// Make a working copy to preserve GUID on write-back
var work = UnityEngine.Object.Instantiate(src);
work.name = src.name;
// === Read Autodesks bulllshit properties ===
// Textures
var albedoTex = work.GetTexture("_MainTex") as Texture2D;
var metallicTex = (work.GetTexture("_MetallicGlossMap") ?? work.GetTexture("_MetallicMap")) as Texture2D; // some variants
var roughTex = (work.GetTexture("_SpecGlossMap") ?? work.GetTexture("_RoughnessMap")) as Texture2D; // Autodesk calls it "Roughness Map"
var normalTex = work.GetTexture("_BumpMap") as Texture2D;
var aoTex = work.GetTexture("_OcclusionMap") as Texture2D;
var emisTex = work.GetTexture("_EmissionMap") as Texture2D;
// Scalars/Colors
var baseColor = work.HasProperty("_Color") ? work.GetColor("_Color") : Color.white;
var bumpScale = work.HasProperty("_BumpScale") ? work.GetFloat("_BumpScale") : 1f;
var cutoff = work.HasProperty("_Cutoff") ? work.GetFloat("_Cutoff") : 0f;
var emissionColor = work.HasProperty("_EmissionColor") ? work.GetColor("_EmissionColor") : Color.black;
// ST (tiling/offset) from Autodesk "_MainTex"
var albedoScale = work.HasProperty("_MainTex") ? work.GetTextureScale("_MainTex") : Vector2.one;
var albedoOffset = work.HasProperty("_MainTex") ? work.GetTextureOffset("_MainTex") : Vector2.zero;
// Double-sided hint from cull
int cull = work.HasProperty("_Cull") ? work.GetInt("_Cull") : (int)CullMode.Back;
bool doubleSided = (CullMode)cull == CullMode.Off;
// Transparent / Cutout hints
bool isCutout = work.IsKeywordEnabled("_ALPHATEST_ON") || cutoff > 0f;
bool isTransparent = !isCutout && src.renderQueue >= (int)RenderQueue.Transparent;
// === Switch to HDRP/Lit ===
work.shader = Shader.Find("HDRP/Lit");
if (work.shader == null)
{
Debug.LogError("HDRP/Lit shader not found. Is HDRP installed?");
UnityEngine.Object.DestroyImmediate(work);
return;
}
// Base color + map
if (albedoTex) work.SetTexture("_BaseColorMap", albedoTex);
work.SetColor("_BaseColor", baseColor);
if (albedoTex)
{
work.SetTextureScale("_BaseColorMap", albedoScale);
work.SetTextureOffset("_BaseColorMap", albedoOffset);
}
// Normal map + strength
if (normalTex)
{
work.SetTexture("_NormalMap", normalTex);
work.SetFloat("_NormalScale", bumpScale);
work.SetTextureScale("_NormalMap", albedoScale);
work.SetTextureOffset("_NormalMap", albedoOffset);
}
// Pack and assign HDRP Mask Map (R=Metallic, G=AO, B=DetailMask, A=Smoothness)
// Smoothness = 1 - Roughness (Autodesk roughness map)
Texture2D maskMap = TryBuildMaskMap(assetPath, src.name, metallicTex, aoTex, roughTex);
if (maskMap != null)
{
work.SetTexture("_MaskMap", maskMap);
work.SetFloat("_Metallic", 1f); // use map as authority
work.SetFloat("_Smoothness", 1f); // use A channel in mask map
work.SetTextureScale("_MaskMap", albedoScale);
work.SetTextureOffset("_MaskMap", albedoOffset);
}
else
{
// Fallback: no packing possible — keep sliders reasonable
// If Autodesk had a scalar roughness, invert into smoothness if you happen to find it.
if (work.HasProperty("_Roughness"))
work.SetFloat("_Smoothness", 1f - Mathf.Clamp01(work.GetFloat("_Roughness")));
}
// Emission (HDRP stores final intensity in _EmissiveColor)
if (emisTex) work.SetTexture("_EmissiveColorMap", emisTex);
if (emissionColor.maxColorComponent > 0f || emisTex)
{
work.SetColor("_EmissiveColor", emissionColor);
work.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
}
// Alpha cutout / transparency / double-sided
work.SetFloat("_AlphaCutoffEnable", isCutout ? 1f : 0f);
if (isCutout) work.SetFloat("_AlphaCutoff", cutoff);
work.SetFloat("_SurfaceType", isTransparent ? 1f : 0f); // 0=Opaque, 1=Transparent
if (isTransparent) work.SetFloat("_BlendMode", 0f); // 0=Alpha
work.SetFloat("_DoubleSidedEnable", doubleSided ? 1f : 0f);
// Validate to make HDRP update keywords & internal state
HDMaterial.ValidateMaterial(work);
// Write back into the original asset to keep GUID
Undo.RecordObject(src, "Convert to HDRP/Lit");
EditorUtility.CopySerialized(work, src);
EditorUtility.SetDirty(src);
UnityEngine.Object.DestroyImmediate(work);
}
private static Texture2D TryBuildMaskMap(
string srcMatPath, string matName,
Texture2D metallicTex, Texture2D aoTex, Texture2D roughnessTex)
{
if (metallicTex == null && aoTex == null && roughnessTex == null)
return null;
// Choose a reference size
int w = 0, h = 0;
var refTex = metallicTex ?? aoTex ?? roughnessTex;
w = refTex.width; h = refTex.height;
// Ensure readable copies
var met = EnsureReadableCopy(metallicTex);
var ao = EnsureReadableCopy(aoTex);
var rou = EnsureReadableCopy(roughnessTex);
var packed = new Texture2D(w, h, TextureFormat.RGBA32, refTex.mipmapCount > 1);
packed.name = $"{matName}_MaskMap";
for (int y = 0; y < h; y++)
{
float v = (y + 0.5f) / h;
for (int x = 0; x < w; x++)
{
float u = (x + 0.5f) / w;
float r = met ? met.GetPixelBilinear(u, v).r : 0.0f; // Metallic
float g = ao ? ao.GetPixelBilinear(u, v).r : 1.0f; // AO (default 1)
float b = 0.0f; // DetailMask (unused)
float a = rou ? 1.0f - rou.GetPixelBilinear(u, v).r : 0.5f; // Smoothness = 1 - roughness
packed.SetPixel(x, y, new Color(r, g, b, a));
}
}
packed.Apply(true, false);
// Save as PNG next to material
string dir = Path.GetDirectoryName(srcMatPath);
string texPath = Path.Combine(dir ?? "Assets", packed.name + ".png").Replace('\\', '/');
File.WriteAllBytes(texPath, packed.EncodeToPNG());
AssetDatabase.ImportAsset(texPath);
// Import as Linear (sRGB off) per HDRP mask map requirement
var ti = (TextureImporter)AssetImporter.GetAtPath(texPath);
if (ti != null)
{
ti.sRGBTexture = false;
ti.alphaIsTransparency = false;
ti.mipmapEnabled = refTex.mipmapCount > 1;
ti.textureCompression = TextureImporterCompression.Compressed;
ti.SaveAndReimport();
}
return AssetDatabase.LoadAssetAtPath<Texture2D>(texPath);
}
private static Texture2D EnsureReadableCopy(Texture2D src)
{
if (!src) return null;
// Make importer readable temporarily
string path = AssetDatabase.GetAssetPath(src);
var ti = (TextureImporter)AssetImporter.GetAtPath(path);
bool restoreReadable = false;
if (ti != null && !ti.isReadable)
{
restoreReadable = true;
ti.isReadable = true;
ti.SaveAndReimport();
}
// Copy pixels
var copy = new Texture2D(src.width, src.height, TextureFormat.RGBA32, src.mipmapCount > 1, false);
Graphics.CopyTexture(src, copy);
// If CopyTexture fails for some formats, fall back to CPU read
try
{
if (copy.width != src.width || copy.height != src.height || copy.mipmapCount != src.mipmapCount)
{
copy = new Texture2D(src.width, src.height, TextureFormat.RGBA32, src.mipmapCount > 1, false);
copy.SetPixels(src.GetPixels());
copy.Apply(true, false);
}
}
catch
{
copy = new Texture2D(src.width, src.height, TextureFormat.RGBA32, src.mipmapCount > 1, false);
copy.SetPixels(src.GetPixels());
copy.Apply(true, false);
}
// Restore importer flag
if (restoreReadable && ti != null)
{
ti.isReadable = false;
ti.SaveAndReimport();
}
return copy;
}
}
#endif