700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Unity Fbx转Prefab工具

Unity Fbx转Prefab工具

时间:2022-04-26 21:31:05

相关推荐

Unity Fbx转Prefab工具

1.功能描述

a.可将fbx直接导出prefab。

b.同时为prefab预先按需挂载脚本文件。

c.同时为挂载的脚本设置参数,绑定资源等。

d.批量化处理,递归遍历算法,高效可扩展。

2.实现方式

a.Editor类

using Lean.Touch;using Main;using System;using System.Collections.Generic;using ponentModel;using System.Linq;using System.Reflection;using UnityEditor;using UnityEngine;public enum SystemBody{[Description("Bones")]guge=1,[Description("Muscle")]jirou,[Description("Vein")]jingmai,[Description("Aetery")]dongmai,[Description("Bones")]neifenmi=5,[Description("Bones")]shenjing,[Description("Skin")]pifu,[Description("Lymph")]lingba,[Description("GenitourinrySelectable")]miniaoshengzhi,[Description("Respiratory")]xiaohua=10,[Description("Joint")]guanjie,[Description("Respiratory")]huxi,}public static class EnumExpand{public static T ToEnum<T>(this string str){return (T)Enum.Parse(typeof(T), str);}}public class Fbx2Prefab : Editor{[MenuItem("Assets/Fbx2Prefab/Create GuGe Prefab")]public static void CreateGuGePre(){GameObject obj = Selection.gameObjects[0];GameObject pre = MonoBehaviour.Instantiate(obj);List<GameObject> prelist = new List<GameObject>();for (int i = 0; i < pre.transform.childCount; i++){prelist.Add(pre.transform.GetChild(i).gameObject);}GameObjectTree tree = MonoBehaviour.FindObjectOfType<GameObjectTree>();tree.scriptObjs.Clear();tree.rootTransform = pre.transform;tree.scriptObjs.Add(MonoScript.FromScriptableObject(CreateInstance(typeof(BonesSelectable))));tree.scriptObjs.Add(MonoScript.FromScriptableObject(CreateInstance(typeof(LeanSelectableByFinger))));tree.AddMonoScript();var mts = Resources.FindObjectsOfTypeAll<Material>();//绑定材质球tree.SetCommponentValue<BonesSelectable>(mts.ToList().Find(p=>p.name== SystemBody.guge.ToString())); foreach (var item in prelist){PrefabUtility.SaveAsPrefabAsset(item, $"Assets/Prefab/{item.name}.prefab");}DestroyImmediate(pre);}[MenuItem("Assets/Fbx2Prefab/Create Jirou Prefab")]public static void CreateJirouPre(){SystemBody body = SystemBody.jirou;CreateNormalPre(body);}[MenuItem("Assets/Fbx2Prefab/Create Normal Prefab")]public static void CreateNormalPre(){SystemBody body = SystemBody.jirou;string n = Selection.gameObjects[0]?.name;if (string.IsNullOrEmpty(n)){Debug.LogError("未选中");}else{body = n.ToLower().ToEnum<SystemBody>();}CreateNormalPre(body);}public static void CreateNormalPre(SystemBody body){GameObject obj = Selection.gameObjects[0];GameObject pre = MonoBehaviour.Instantiate(obj);List<GameObject> prelist = new List<GameObject>();for (int i = 0; i < pre.transform.childCount; i++){prelist.Add(pre.transform.GetChild(i).gameObject);}GameObjectTree tree = MonoBehaviour.FindObjectOfType<GameObjectTree>();tree.scriptObjs.Clear();tree.rootTransform = pre.transform;Type t = Assembly.Load("Unity.ModelView").GetType($"Main.{body.GetDescName()}Selectable");tree.scriptObjs.Add(MonoScript.FromScriptableObject(CreateInstance(t)));tree.scriptObjs.Add(MonoScript.FromScriptableObject(CreateInstance(typeof(LeanSelectableByFinger))));tree.AddMonoScript();var mts = Resources.FindObjectsOfTypeAll<Material>();//绑定材质球tree.SetTypeValue(t, mts.ToList().Find(p => p.name == body.ToString()));foreach (var item in prelist){PrefabUtility.SaveAsPrefabAsset(item, $"Assets/Prefab/{item.name}.prefab");}DestroyImmediate(pre);}}

b.迭代器(注意:没有必要搞懂迭代如何实现,能用起来就可以)放心直接考到工程就可以用

using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Reflection;using System.Text;using Newtonsoft.Json;using UnityEditor;using UnityEngine;using UnityEngine.UI;public class GameObjectTree : MonoBehaviour{#region 零时脚本#endregionpublic Transform rootTransform;public Hashtable gameTs;public Font font;#if UNITY_EDITORpublic List<MonoScript> scriptObjs;#endif/// <summary>/// 透明 /// </summary>public Material disableMat, leafMat, NodeMat;[ContextMenu("遍历对象并打印")]public void Traverse(){RecursiveTraverse(rootTransform, (tran) => Debug.Log(tran.name));}[ContextMenu("AddMeshCollider")]public void AddMeshColliderScript(){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out MeshRenderer renderer)){if (!tran.TryGetComponent(out MeshCollider b)){tran.AddComponent<MeshCollider>();}}});}[ContextMenu("ChangeJRTag")]public void ChangeJRTag(){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out MeshRenderer renderer)){if (!tran.TryGetComponent(out MeshCollider b)){tran.AddComponent<MeshCollider>();}tran.tag = "JR";}});}[ContextMenu("ChangeGGTag")]public void ChangeGGTag(){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out MeshRenderer renderer)){if (!tran.TryGetComponent(out MeshCollider b)){tran.AddComponent<MeshCollider>();}tran.tag = "GG";}});}[ContextMenu("RemoveMeshCollider")]public void RemoveMeshColliderScript(){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out MeshRenderer renderer)){if (tran.TryGetComponent(out MeshCollider b)){DestroyImmediate(b);}}});}#if UNITY_EDITOR[ContextMenu("AddMonoScriptUnderMeshRenderer")]public void AddMonoScript(){List<Type> types = new List<Type>();foreach (var item in scriptObjs){types.Add(item.GetClass());}RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out MeshRenderer renderer)){foreach (var item in types){if (tran.TryGetComponent(item, out Component sss)){DestroyImmediate(sss);}tran.gameObject.AddComponent(item);}Debug.Log(tran.name);if (!tran.TryGetComponent(out MeshCollider mesh)){tran.AddComponent<MeshCollider>();}}});}public void SetCommponentValue<T>(Material m){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out T t)){var v = t.GetType();FieldInfo info = v.GetField("setMt");info.SetValue(t, m);}});}public void SetTypeValue(Type t,Material m){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(t, out Component c)){var v = c.GetType();FieldInfo info = v.GetField("setMt");info.SetValue(c, m);}});}[ContextMenu("RemoveMonoScript")]public void RemoveMonoScript(){List<Type> types = new List<Type>();foreach (var item in scriptObjs){types.Add(item.GetClass());}RecursiveTraverse(rootTransform, (tran) =>{foreach (var item in types){if (tran.TryGetComponent(item, out Component sss)){DestroyImmediate(sss);}}});}#endif[ContextMenu("RemoveNameSpace")]public void RemoveNameSpace(){RecursiveTraverse(rootTransform, (tran) =>{string _name = tran.gameObject.name;if (_name.Contains(" ")){Debug.Log(_name);tran.gameObject.name = _name.Replace(" ", "");}});}[ContextMenu("RemoveBoxCollider")]public void RemoveBoxCollider(){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out BoxCollider renderer)){DestroyImmediate(renderer);}});}[ContextMenu("AddMissingFont")]public void AddMissingFont(){RecursiveTraverse(rootTransform, (tran) =>{if (tran.TryGetComponent(out Text renderer) && renderer.font == null){renderer.font = font;}});}[ContextMenu("遍历隐藏")]public void Disable(){RecursiveTraverse(rootTransform, (tran) => { tran.TryGetComponent(out Renderer renderer); renderer.material = disableMat; });}[ContextMenu("遍历显示")]public void EanbleRecurise(){RecursiveTraverse(rootTransform, (tran) => { tran.TryGetComponent(out Renderer renderer); renderer.material = NodeMat; });}[ContextMenu("生成模型快照-1")]public void CreateTreeState(){StringBuilder sb = new StringBuilder();var Root = TreeNode<Transform>.CopyTransformHierarchy(rootTransform, tran =>{return tran;});Root.TraverseDown((s) =>{if (IsActive(s.Name) && IsMeshFilter(s.Name)){sb.Append($"{ s.Name.name},");}});GUIUtility.systemCopyBuffer = sb.ToString();//Clipboard.Copy();// WriteFile("mapData.json", sb.ToString());}bool IsActive(Transform t){return t.gameObject.activeSelf;}bool IsMeshFilter(Transform t){return t.TryGetComponent(out MeshFilter n);}[ContextMenu("构造树")]public void ConstructTree(){treeRootNode = TreeNode<string>.CopyTransformHierarchy(rootTransform, tran => tran.name);var json = PreserveRefToJson(treeRootNode);UnityEngine.Debug.Log(json);WriteFile("treeNode.json", json);// var reload = ReadFile("treeNode.json");//比较//var reloadNode = PreserveRefFromJson<TreeNode<string>>(reload);//if (PreserveRefToJson(reloadNode).Equals(json))//{// Debug.Log("相等");//}// string info = treeRootNode.Print(node => GetIndent(node.GetLevel()) + node.Name);// Debug.Log(info);}[ContextMenu("读取保存到文件中的树")]public void ReadTree(){string json = ReadFile("treeNode.json");var reload = PreserveRefFromJson<TreeNode<string>>(json);}public void RecursiveTraverse(Transform tran, Action<Transform> op = null){op?.Invoke(tran);for (int i = 0; i < tran.childCount; i++){var child = tran.GetChild(i);RecursiveTraverse(child, op);}}public TreeNode<string> treeRootNode = new TreeNode<string>();// public TreeNode<string> CopyTransformHierarchy(Transform tran, TreeNode<string> NodeParent = null) {//TreeNode<string> curNode = new TreeNode<string>();//curNode.Payload = tran.name;//NodeParent?.AddChild(curNode);//for (int i = 0; i < tran.childCount; i++) {// var child = tran.GetChild(i);// CopyTransformHierarchy(child, curNode);//}////return curNode;// }#region utilspublic string GetIndent(int n){StringBuilder sb = new StringBuilder();for (int i = 0; i < n; i++){sb.Append("=");}sb.Append("|");return sb.ToString();}public string PreserveRefToJson<T>(T obj){var json = JsonConvert.SerializeObject(obj, Formatting.None, /*Formatting.Indented,*/new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });return json;}public T PreserveRefFromJson<T>(string json){T reload = JsonConvert.DeserializeObject<T>(json,new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.All });return reload;}public void WriteFile(string fileName, string content){File.WriteAllText(Application.streamingAssetsPath + Path.DirectorySeparatorChar + fileName, content);}public string ReadFile(string fileName){return File.ReadAllText(Application.streamingAssetsPath + Path.DirectorySeparatorChar + fileName);}#endregion/** 目前两套方案,一套是复制一份prefab,然后将prefab的模型层级修改成目标层级,解析这个层级来获得配置信息* 另一套方案就是完全用目录结构来重建目标层级,* 在现有的机制下,先构造一套统一的抽象,然后分别用解析文件系统,和解析gameobject 的 transform层级来实现。*/}public class TreeNode<T>{public T Name { get; set; }public TreeNode<T> Parent { get; set; }public List<TreeNode<T>> Children;public bool IsRoot() => Parent == null;public bool IsLeaf() => Children == null;public void AddChild(TreeNode<T> node){// Children ??= new List<TreeNode<T>>();if (Children == null) Children = new List<TreeNode<T>>();Children.Add(node);node.Parent = this;}public List<TreeNode<T>> Siblings(){return Parent?.Children ?? null;}public int SiblingCount(){return Parent?.Children?.Count ?? 0;}/// <summary>/// 向下递归遍历所有children,实际会遍历以当前node为root的子树/// </summary>public void TraverseDown(Action<TreeNode<T>> nodeAction){nodeAction?.Invoke(this);Children?.ForEach(child => child.TraverseDown(nodeAction));}/// <summary>/// 向上遍历所有parent,相当与遍历当前node为head,终止node为root的链表/// </summary>public void TraverseUp(Action<TreeNode<T>> nodeAction){nodeAction?.Invoke(this);Parent?.TraverseUp(nodeAction);}/// <summary>/// 递归函数的结构就定义了递归的条件,你无法额外插入新的终止条件,除非你重写这个递归./// 所以这个Find方法,原本只想找到第一个命中就退出,但发现利用TraverseDown是无法立即停下的,/// 即使找到一个命中元素,仍然要完成所有遍历,所以干脆就改了一下实现,Find是找到所有/// </summary>/// <param name="predicate"></param>/// <returns></returns>public List<TreeNode<T>> Find(Predicate<TreeNode<T>> predicate){List<TreeNode<T>> resultList = new List<TreeNode<T>>();TraverseDown((node) =>{if (predicate(node)){resultList.Add(node);}});return resultList;}public TreeNode<T> FindRoot(){TreeNode<T> current = this;while (current.Parent != null){current = current.Parent;}return current;}/// <summary>/// 获得当前Node在树中的深度,root深度值为0,每向下前进一级,level++/// </summary>/// <returns></returns>public int GetLevel(){int level = 0;TreeNode<T> current = this;while (current.Parent != null){current = current.Parent;level++;}return level;}public string Print(Func<TreeNode<T>, string> ToString){StringBuilder sb = new StringBuilder();TraverseDown(node =>{string info = ToString(node);sb.AppendLine(info);});return sb.ToString();}/// <summary>/// 以一个transform为root,将其hierarchy结构映射成一个TreeNode<T>表达的树,返回root Node/// 想要构建一个树状信息图,必须找一个本身就是树状结构的对象,比如transform,比如文件目录,所以这里不需要再用泛型来表达这一层,直接假设目标是Transform/// </summary>/// <param name="tran">以这个transform为起点开始遍历</param>/// <param name="selector">从Transform转换为payload T 的 方法</param>/// <param name="NodeParent">当前节点的父节点(这个需要递归传给每一级子节点来确立父子关系)</param>/// <returns></returns>public static TreeNode<T> CopyTransformHierarchy(Transform tran, Func<Transform, T> selector,TreeNode<T> NodeParent = null){TreeNode<T> curNode = new TreeNode<T>();curNode.Name = selector(tran);NodeParent?.AddChild(curNode);for (int i = 0; i < tran.childCount; i++){var child = tran.GetChild(i);CopyTransformHierarchy(child, selector, curNode);}return curNode;}/// <summary>/// 遍历整个子树,构造所有payload->TreeNode的字典并返回,/// 提供一个通过payload查找的字典/// </summary>/// <returns></returns>public Dictionary<T, TreeNode<T>> GetTreeNodeMap(){Dictionary<T, TreeNode<T>> TreeNodeDict = new Dictionary<T, TreeNode<T>>();TraverseDown(node => { TreeNodeDict.Add(node.Name, node); });return TreeNodeDict;}public Dictionary<K, TreeNode<T>> GetTreeNodeMap<K>(Func<T, K> selector){Dictionary<K, TreeNode<T>> TreeNodeDict = new Dictionary<K, TreeNode<T>>();TraverseDown(node =>{K k = selector(node.Name);TreeNodeDict.Add(k, node);});return TreeNodeDict;}}

c.关键需要注意的方法

Fbx2Prefab.CreateNormalPre()

Fbx2Prefab. CreateNormalPre(SystemBody body)

GameObjectTree.SetTypeValue(Type t,Material m)

GameObjectTree.AddMonoScript()

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。