问题:
- 工作需求需要自定义法线贴图alpha通道
- 贴图格式选择了default
- 但是unity会强制mark as normalmap
回溯源码:
- 三个地方
- model导入的时候 ModelImporterPostProcessor
InternalEditorUtility.PerformUnmarkedBumpMapTexturesFixing(); - MaterialEditor inspector面板
CheckMaterial TextureCompatibilityWarning - BumpMapSettingsFixingWindow
方案:
- 发帖
https://forum.unity.com/threads/how-to-not-display-the-normalnap-settings-window-when-the-normal-map-is-set-to-default-type.886543/ - 代码操作
将法线贴图修改模式改为静默模式
继承AssetPostprocessor类
重写OnPostprocessAllAssets 方法
order设置为0(越小越优先)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditorInternal;
using UnityEngine;
namespace UnityEditor
{
[InitializeOnLoad]
public class EditingClass
{
// 启动将法线贴图修改模式改为静默模式
static EditingClass()
{
Debug.LogError("Unity Awake !");
Assembly asm = Assembly.Load("UnityEditor");
Type testType = asm.GetType("UnityEditor.BumpMapSettings");
foreach (var item in testType.GetProperties())
{
Debug.Log("silentMode" + item.GetValue(testType));
if (item.Name.Equals("silentMode"))
item.SetValue(testType, true);
Debug.Log("silentMode" + item.GetValue(testType));
}
}
}
public class MaterialProcess : AssetPostprocessor
{
public void OnPreprocessTexture()
{
Debug.LogError("pre" + assetPath);
TextureImporter ti = TextureImporter.GetAtPath(assetPath) as TextureImporter;
if (ti.normalmap && ti.DoesSourceTextureHaveAlpha())
{
ti.textureType = TextureImporterType.Default;
Debug.LogError("assetPath " + assetPath);
}
}
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath)
{
foreach (var assetPath in importedAssets)
{
Debug.LogError("all " + assetPath);
var isMaterialAsset = Path.GetExtension(assetPath) == ".mat";
if (isMaterialAsset)
{
// 材质球发生改变的时候,unity内部依然会检测法线贴图格式
var embeddedMaterials = AssetDatabase.LoadAllAssetsAtPath(assetPath).OfType<Material>();
foreach (var material in embeddedMaterials)
{
Shader shader = material.shader;
for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); ++i)
{
if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
{
string propertyName = ShaderUtil.GetPropertyName(shader, i);
Texture tex = material.GetTexture(propertyName);
if (tex == null)
continue;
string texPath = AssetDatabase.GetAssetPath(tex.GetInstanceID());
TextureImporter ti = TextureImporter.GetAtPath(texPath) as TextureImporter;
if (ti.normalmap && ti.DoesSourceTextureHaveAlpha())
{
ti.textureType = TextureImporterType.Default;
Debug.LogError("texPath " + texPath);
}
}
}
}
}
}
}
}
}
然鹅。。。
上面的方法在2018适用
在2017不适用
最终暴力解决
- 继承AssetPostprocessor类
- 重写OnPostprocessAllAssets 方法
- 反射获取BumpMapSettingsFixingWindow窗口类,在delaycall中 关掉它
private static void BumpMapWindowCheck(string[] assetpaths)
{
if (null == assetpaths || assetpaths.Length == 0)
return;
EditorApplication.delayCall += AutoCloseBumpMapSettingWindow;
}
static void AutoCloseBumpMapSettingWindow()
{
Assembly asm = Assembly.Load("UnityEditor");
Type testType = asm.GetType("UnityEditor.BumpMapSettingsFixingWindow");
UnityEngine.Object[] objectsOfTypeAll = UnityEngine.Resources.FindObjectsOfTypeAll(testType);
EditorWindow editorWindow = objectsOfTypeAll.Length <= 0 ? (EditorWindow)null : objectsOfTypeAll[0] as EditorWindow;
if (!(bool)((UnityEngine.Object)editorWindow))
return;
editorWindow.Close();
}