using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; namespace ChivaXR { public class FbxImportSettingTool : EditorWindow { protected static FbxImportSettingTool s_instance = null; internal static FbxImportSettingTool instance { get { if (s_instance == null) { s_instance = GetWindow(); } return s_instance; } } #region 匹配贴图工具 /// /// 在模型和贴图的父级调用,会根据材质球名称和贴图名称检索自动添加贴图 /// [MenuItem("ChivaXR/Tool/自动匹配材质贴图文件")] static void UpdateFbxMaterials() { instance.LoadInit(); Object[] objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); List pngandtga = new List(); for (int i = 0; i < objs.Length; i++) { Object obj = objs[i]; string url = AssetDatabase.GetAssetPath(obj); if (string.IsNullOrEmpty(url)) continue; string ext = Path.GetExtension(url); if (ext == ".tga" || ext == ".TGA" || ext == ".png" || ext == ".PNG") { pngandtga.Add(url); continue; } if (ext != ".fbx" && ext != ".FBX") continue; //如果是fbx加载材质球 instance.LoadMaterials(url); } for (int i = 0; i < pngandtga.Count; i++) { string url = pngandtga[i]; instance.LoadTexture(url); } instance.SettingMaterials(); AssetDatabase.Refresh(); } private List mListMaterial = new List(); private List mListMaterialName = new List(); private Dictionary mDicTexture = new Dictionary(); /// /// 颜色贴图 -贴图的命名规则(材质_目标贴图后缀) /// private string[] AlbedoTexture = new string[] { "_AlbedoTransparency", "_Albedo" }; /// /// 高光贴图 /// private string[] MetallicTexture = new string[] { "_MetallicSmoothness", "_Metallic" }; /// /// 法线贴图 /// private string[] NormalTexture = new string[] { "_Normal" }; /// /// Ao贴图 /// private string[] OcclusionTexture = new string[] { "_Ao", "_AO", "_Occlusion", "_AmbientOcclusion" }; /// /// 初始化 /// private void LoadInit() { mListMaterial.Clear(); mListMaterialName.Clear(); mDicTexture.Clear(); } /// /// 加载所有PBX文件的Material(材质球) /// /// private void LoadMaterials(string url) { ModelImporter modelImporter = ModelImporter.GetAtPath(url) as ModelImporter; modelImporter.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription; modelImporter.materialName = ModelImporterMaterialName.BasedOnMaterialName; modelImporter.materialSearch = ModelImporterMaterialSearch.Everywhere; AssetDatabase.ImportAsset(url); Object obj = AssetDatabase.LoadAssetAtPath(url); GameObject go = obj as GameObject; Renderer[] skins = go.GetComponentsInChildren(true); if (skins.Length == 0) return; for (int i = 0; i < skins.Length; i++) { Renderer renderer = skins[i]; if (renderer.sharedMaterials != null && renderer.sharedMaterials.Length > 0) { for (int j = 0; j < renderer.sharedMaterials.Length; j++) { Material mat = renderer.sharedMaterials[j]; if (mat != null) { mListMaterial.Add(mat); mat.shader = Shader.Find("Standard"); if (!mListMaterialName.Contains(mat.name)) { mListMaterialName.Add(mat.name); } } } } } } /// /// 加载文件中的所有Texture(贴图) /// /// private void LoadTexture(string url) { Texture2D TempTexture = AssetDatabase.LoadAssetAtPath(url); string TempTextureName = TempTexture.name; TextureImporter texture = AssetImporter.GetAtPath(url) as TextureImporter; for (int i = 0; i < AlbedoTexture.Length; i++) { if (DateTexture(AlbedoTexture[i], TextureType.Albedo, TempTexture)) return; } for (int i = 0; i < MetallicTexture.Length; i++) { if (DateTexture(MetallicTexture[i], TextureType.Metallic, TempTexture)) return; } for (int i = 0; i < OcclusionTexture.Length; i++) { if (DateTexture(OcclusionTexture[i], TextureType.Occlusion, TempTexture)) return; } for (int i = 0; i < NormalTexture.Length; i++) { if (DateTexture(NormalTexture[i], TextureType.Normal, TempTexture)) { TextureImporter tempTexture = AssetImporter.GetAtPath(url) as TextureImporter; tempTexture.textureType = TextureImporterType.NormalMap; return; } } } private bool DateTexture(string varTextureName, TextureType varTextureType, Texture Texture) { string TempTextureName = Texture.name; string key = GetMaterialsBuyTexture(TempTextureName, varTextureName); if (mListMaterialName.Contains(key)) { MaterialsDate Date = new MaterialsDate(); if (mDicTexture.ContainsKey(key)) { Date = mDicTexture[key]; } switch (varTextureType) { case TextureType.Albedo: Date.Albedo = Texture; break; case TextureType.Metallic: Date.Metallic = Texture; break; case TextureType.Normal: Date.Normal = Texture; break; case TextureType.Occlusion: Date.Occlusion = Texture; break; default: break; } if (mDicTexture.ContainsKey(key)) { mDicTexture[key] = Date; } else { mDicTexture.Add(key, Date); } return true; } else { return false; } } /// /// 移除指定后缀获取对应材质的名称 /// private string GetMaterialsBuyTexture(string TextureName, string varTextureName) { string key = TextureName; if (TextureName.Contains(varTextureName)) { int index = TextureName.LastIndexOf(varTextureName); key = TextureName.Substring(0, index); } return key; } /// /// 给材质贴上指定的贴图 /// private void SettingMaterials() { for (int i = 0; i < mListMaterial.Count; i++) { string MaterialName = mListMaterial[i].name; Material mat = mListMaterial[i]; if (mat.GetTexture("_MainTex") != null) { //如果有颜色贴图,则将贴图颜色设为白色 mat.SetColor("_Color", Color.white); } if (mDicTexture.ContainsKey(MaterialName)) { var date = mDicTexture[MaterialName]; if (date.Albedo != null) mat.SetTexture("_MainTex", date.Albedo); if (date.Metallic != null) mat.SetTexture("_MetallicGlossMap", date.Metallic); if (date.Normal != null) mat.SetTexture("_BumpMap", date.Normal); if (date.Occlusion != null) mat.SetTexture("_OcclusionMap", date.Occlusion); } else { Debug.LogError("Materials :" + MaterialName + "Texture Not Existent"); } } } public struct MaterialsDate { public Texture Albedo; public Texture Metallic; public Texture Normal; public Texture Occlusion; } public enum TextureType { Albedo, Metallic, Normal, Occlusion, } #endregion #region UnityAnimation 动画片段切分工具 /// /// FBX动画自动分段工具 /// 使用:需要将配置表和模型放入同一个文件夹 /// 配置表与模型同名,格式为(.txt): /// 配置表内容 片段名称(nullOrEmpty会自动填充为step+"n"),0-100 /// ,101-200 /// ,201-300类推 /// [MenuItem("Assets/Chiva/动画片段切分")] static void AnimationClipCreator() { try { Object obj = Selection.activeObject; string AssetPath = AssetDatabase.GetAssetPath(obj); List fbxModelList = new List(); //替换后缀 string text = Path.ChangeExtension(AssetPath, ".txt"); StreamReader file = new StreamReader(text); string clipInfo = file.ReadToEnd(); file.Close(); string[] clipInfosArr = clipInfo.Split('\n'); Debug.Log("length:" + clipInfosArr.Length); for (int i = 0; i < clipInfosArr.Length; i++) { string[] infos = clipInfosArr[i].Split(','); string[] frameInfo = infos[1].Split('-'); FbxModel fbxModel = new FbxModel(); fbxModel.firstFrame = int.Parse(frameInfo[0]); fbxModel.lastFrame = int.Parse(frameInfo[1]); if (string.IsNullOrEmpty(infos[0])) { fbxModel.name = "step" + (i + 1); } else { fbxModel.name = infos[0]; } //bool isLoop = info[3] == "0" ? true : false; //bool isLoop = bool.Parse(info[3]); //Debug.Log("是否循环" + isLoop); //fbxModel.loopTime = isLoop; //fbxModel.loopPose = isLoop; fbxModelList.Add(fbxModel); } //模型导入器 ModelImporter modelImporter = ModelImporter.GetAtPath(AssetPath) as ModelImporter; ArrayList clipsList = new ArrayList(); for (int i = 0; i < fbxModelList.Count; i++) { //动画片段 ModelImporterClipAnimation clipAnimation = new ModelImporterClipAnimation(); clipAnimation.name = fbxModelList[i].name; clipAnimation.firstFrame = fbxModelList[i].firstFrame; clipAnimation.lastFrame = fbxModelList[i].lastFrame; clipAnimation.loopTime = fbxModelList[i].loopTime; clipAnimation.loopPose = fbxModelList[i].loopPose; clipsList.Add(clipAnimation); } modelImporter.clipAnimations = (ModelImporterClipAnimation[])clipsList.ToArray(typeof(ModelImporterClipAnimation)); AssetDatabase.ImportAsset(AssetPath); AssetDatabase.Refresh(); } catch (System.Exception e) { EditorUtility.DisplayDialog("导入错误", e.ToString(), "关闭"); } } #endregion } public class FbxModel { public string name; public int firstFrame; public int lastFrame; public bool loopTime; public bool loopPose; } }