Prefab上面会有很多多余的引用记录在文件上,打包的时候获取依赖会一起打包进去,可以通过EditorUtility.SetDirty(Object)这个接口去刷
ParticleSystemRender的话会有另外的问题,如果使用过Mesh Mode的话,他会保存模型引用,也是非常让人费解。。需要如下清除:
public static bool CheckParticleSystemRenderer(GameObject gameObj)
{
bool isChange = false;
ParticleSystemRenderer[] renders = gameObj.GetComponentsInChildren<ParticleSystemRenderer>(true);
foreach (var renderItem in renders)
{
if (renderItem.renderMode != ParticleSystemRenderMode.Mesh)
{
renderItem.mesh = null;
isChange = true;
}
}
return isChange;
}
材质球的话,也会有非常多的乱七八糟引用。setdirty也是不能解决,只能直接改序列化文件了
public static void CleanMaterial(Material mat)
{
if (mat && mat.shader != null)
{
SerializedObject psSource = new SerializedObject(mat);
SerializedProperty emissionProperty = psSource.FindProperty("m_SavedProperties");
SerializedProperty texEnvs = emissionProperty.FindPropertyRelative("m_TexEnvs");
SerializedProperty floats = emissionProperty.FindPropertyRelative("m_Floats");
SerializedProperty colos = emissionProperty.FindPropertyRelative("m_Colors");
bool rebuild1 = CleanMaterialSerializedProperty(texEnvs, mat);
bool rebuild2 = CleanMaterialSerializedProperty(floats, mat);
bool rebuild3 = CleanMaterialSerializedProperty(colos, mat);
if (rebuild1 || rebuild2 || rebuild3)
{
psSource.ApplyModifiedProperties();
EditorUtility.SetDirty(mat);
}
}
}
private static bool CleanMaterialSerializedProperty(SerializedProperty property, Material mat)
{
bool rebuild = false;
for (int j = property.arraySize - 1; j >= 0; j--)
{
string propertyName = property.GetArrayElementAtIndex(j).displayName;
if (!mat.HasProperty(propertyName))
{
property.DeleteArrayElementAtIndex(j);
rebuild = true;
}
}
return rebuild;
}
FBX材质球导入的时候,也会存在历史记录的问题,但是这个一般比较难以发现,比如下图中,之前美术导入的FBX材质球并不是如下命名,这样在meta文件中就会残留之前的材质球命名,如果材质球刚好还引用了不正确的材质球被保存下来。那样打包跟加载的时候就会加载多余的材质球。下图的svn就是清理前后的对比。最后老规矩,贴上代码。
public static void CleanFbxDependenciesMatiral(string assetPath)
{
GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
Renderer[] renderList = obj.GetComponentsInChildren<Renderer>();
List<Material> materialList = new List<Material>();
foreach (Renderer render in renderList)
{
materialList.AddRange(render.sharedMaterials);
}
ModelImporter mi = AssetImporter.GetAtPath(assetPath) as ModelImporter;
SerializedObject psSource = new SerializedObject(mi);
SerializedProperty property = psSource.FindProperty("m_ExternalObjects");
if (property == null)
return;
for (int j = property.arraySize - 1; j >= 0; j--)
{
SerializedProperty typeStr = property.GetArrayElementAtIndex(j).FindPropertyRelative("first").FindPropertyRelative("type");
if (typeStr.stringValue != "UnityEngine:Material")
{
continue;
}
SerializedProperty firstProperty = property.GetArrayElementAtIndex(j).FindPropertyRelative("second");
if (firstProperty.objectReferenceValue == null)
{
property.DeleteArrayElementAtIndex(j);
}
else if (firstProperty.objectReferenceValue is Material)
{
Material m = firstProperty.objectReferenceValue as Material;
if (!materialList.Contains(m))
property.DeleteArrayElementAtIndex(j);
//Debug.LogFormat("{0},{1},{2}", firstProperty.objectReferenceInstanceIDValue, firstProperty.objectReferenceValue, materialList.Contains(m));
}
}
if (psSource.hasModifiedProperties)
{
psSource.ApplyModifiedProperties();
Debug.Log("hasModifiedProperties:" + assetPath);
AssetDatabase.WriteImportSettingsIfDirty(assetPath);
}
}