Unity批量生成Prefab
在项目中有时会遇到批量生成Prefab的需求。于是写了一个编辑器,用来实现此功能。
在Hierarchy面板中选中多个GameObject,点击生成Prefab即可。
如果所选物体中包含自定义Mesh,需要先在指定目录生成Obj,再将Obj包含的网格赋值给新生成的Prefab。
编辑器脚本如下:
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
/// <summary>
/// CreatePrefabs类为批量创建Prefab的窗口类,选择Hierarchy窗口的物体,点击创建Prefab即可在指定目录生成Prefab
/// 如果所选物体含有动态创建的Mesh,必须先在指定目录先生成OBJ文件
/// </summary>
public class CreatePrefabs : EditorWindow
{
[MenuItem("AssetsManager/批量生成Prefab")] static void AddWindow()
{
//创建窗口
CreatePrefabs window = (CreatePrefabs)EditorWindow.GetWindow(typeof(CreatePrefabs), false, "批量生成Prefab");
window.Show(); } //输入文字的内容
private string PrefabPath = "Assets/Resources/";
private string ObjPath = @"Assets/Obj/";
GameObject[] selectedGameObjects; [InitializeOnLoadMethod]
public void Awake()
{
OnSelectionChange();
}
void OnGUI()
{
GUIStyle text_style = new GUIStyle();
text_style.fontSize = ;
text_style.alignment = TextAnchor.MiddleCenter; EditorGUILayout.BeginHorizontal();
GUILayout.Label("Prefab导出路径:");
PrefabPath = EditorGUILayout.TextField(PrefabPath);
if (GUILayout.Button("浏览"))
{ EditorApplication.delayCall += OpenPrefabFolder; }
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal(); GUILayout.Label(" Obj导出路径:");
ObjPath = EditorGUILayout.TextField(ObjPath);
if (GUILayout.Button("浏览"))
{ EditorApplication.delayCall += OpenObjFolder; }
EditorGUILayout.EndHorizontal(); GUILayout.Label("当前选中了" + selectedGameObjects.Length + "个物体", text_style);
if (GUILayout.Button("如果包含动态创建的Mesh,请先点击生成Obj", GUILayout.MinHeight()))
{
foreach (GameObject m in selectedGameObjects)
{
CreateObj(m);
}
AssetDatabase.Refresh();
}
if (GUILayout.Button("生成当前选中物体的Prefab", GUILayout.MinHeight()))
{
if (selectedGameObjects.Length <= )
{
//打开一个通知栏
this.ShowNotification(new GUIContent("未选择所要导出的物体"));
return;
}
if (!Directory.Exists(PrefabPath))
{
Directory.CreateDirectory(PrefabPath);
}
foreach (GameObject m in selectedGameObjects)
{
CreatePrefab(m, m.name);
}
AssetDatabase.Refresh();
}
} void OpenPrefabFolder()
{
string path = EditorUtility.OpenFolderPanel("选择要导出的路径", "", "");
if (!path.Contains(Application.dataPath))
{
Debug.LogError("导出路径应在当前工程目录下");
return;
}
if (path.Length != )
{
int firstindex = path.IndexOf("Assets");
PrefabPath = path.Substring(firstindex) + "/";
EditorUtility.FocusProjectWindow();
}
} void OpenObjFolder()
{
string path = EditorUtility.OpenFolderPanel("选择要导出的路径", "", "");
if (!path.Contains(Application.dataPath))
{
Debug.LogError("导出路径应在当前工程目录下");
return;
}
if (path.Length != )
{
int firstindex = path.IndexOf("Assets");
ObjPath = path.Substring(firstindex) + "/";
EditorUtility.FocusProjectWindow();
}
} void CreateObj(GameObject go)
{
if (!Directory.Exists(ObjPath))
{
Directory.CreateDirectory(ObjPath);
}
MeshFilter[] meshfilters = go.GetComponentsInChildren<MeshFilter>();
if (meshfilters.Length > )
{
for (int i = ; i < meshfilters.Length; i++)
{
ObjExporter.MeshToFile(meshfilters[i], ObjPath + meshfilters[i].gameObject.name + ".obj"); }
}
}
/// <summary>
/// 此函数用来根据某物体创建指定名字的Prefab
/// </summary>
/// <param name="go">选定的某物体</param>
/// <param name="name">物体名</param>
/// <returns>void</returns>
void CreatePrefab(GameObject go, string name)
{
//先创建一个空的预制物体
//预制物体保存在工程中路径,可以修改("Assets/" + name + ".prefab");
GameObject tempPrefab = PrefabUtility.CreatePrefab(PrefabPath + name + ".prefab", go); MeshFilter []meshfilters= go.GetComponentsInChildren<MeshFilter>();
if (meshfilters.Length > )
{
MeshFilter[] prefabmeshfilters = tempPrefab.GetComponentsInChildren<MeshFilter>();
for (int i = ; i < meshfilters.Length; i++)
{
Mesh m_mesh = AssetDatabase.LoadAssetAtPath<Mesh>(ObjPath + meshfilters[i].gameObject.name + ".obj");
prefabmeshfilters[i].sharedMesh = m_mesh;
}
}
//返回创建后的预制物体
} void OnInspectorUpdate()
{
//这里开启窗口的重绘,不然窗口信息不会刷新
this.Repaint();
} void OnSelectionChange()
{
//当窗口出去开启状态,并且在Hierarchy视图中选择某游戏对象时调用
selectedGameObjects = Selection.gameObjects; }
}
CreatePrefabs
using UnityEngine;
using System.Collections;
using System.IO;
using System.Text; public class ObjExporter
{ public static string MeshToString(MeshFilter mf)
{
Mesh m = mf.sharedMesh;
// Material[] mats = mf.GetComponent<MeshRenderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n");
for(int i=;i<m.vertices.Length;i++)
sb.Append(string.Format("v {0} {1} {2}\n", -m.vertices[i].x, m.vertices[i].y, m.vertices[i].z));
sb.Append("\n");
for (int i = ; i < m.normals.Length; i++)
sb.Append(string.Format("vn {0} {1} {2}\n", -m.normals[i].x, m.normals[i].y, m.normals[i].z));
sb.Append("\n");
for (int i = ; i < m.uv.Length; i++)
sb.Append(string.Format("vt {0} {1}\n",m.uv[i].x, m.uv[i].y)); for (int material = ; material < m.subMeshCount; material++)
{
sb.Append("\n"); int[] triangles = m.GetTriangles(material);
for (int i = ; i < triangles.Length; i += )
{
//Because we inverted the x-component, we also needed to alter the triangle winding.
sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n",
triangles[i] + , triangles[i + ] + , triangles[i + ] + ));
}
}
return sb.ToString();
} public static void MeshToFile(MeshFilter mf, string filename)
{
using (StreamWriter sw = new StreamWriter(filename))
{
sw.Write(MeshToString(mf));
}
}
}
ObjExporter
Unity批量生成Prefab的更多相关文章
- unity工具IGamesTools之批量生成帧动画
unity工具IGamesTools批量生成帧动画,可批量的将指定文件夹下的帧动画图片自动生成对应的资源文件(Animation,AnimationController,Prefabs) unity工 ...
- 将表里的数据批量生成INSERT语句的存储过程 增强版
将表里的数据批量生成INSERT语句的存储过程 增强版 有时候,我们需要将某个表里的数据全部或者根据查询条件导出来,迁移到另一个相同结构的库中 目前SQL Server里面是没有相关的工具根据查询条件 ...
- 脚本工具(获取某个文件夹下的所有图片属性批量生成css样式)
问题描述: 由于有一次工作原因,就是将某个文件夹下的所有图片,通过CSS描述他们的属性,用的时候就可以直接引用.但是我觉得那个文件夹下的图片太多,而且CSS文件的格式又有一定的规律,所有想通过脚本来生 ...
- 代码批量生成WORD的遇到的问题及解决
好久没搞工具了,最近因为处理大规模公文处理单文档,自己写了个批量处理WORD的程序:在调试过程中,主要遇到两个问题 第一个是WORD的模板 数据很多,但是WORD模板只需要一个,将数据替换WORD里标 ...
- FluentData-新型轻量级ORM 利用T4模板 批量生成多文件 实体和业务逻辑 代码
FluentData,它是一个轻量级框架,关注性能和易用性. 下载地址:FlunenData.Model 利用T4模板,[MultipleOutputHelper.ttinclude]批量生成多文件 ...
- 使用html2canvas实现批量生成条形码
/*前台代码*/ <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Generat ...
- 用ticons指令结合ImageMagickDisplay工具批量生成Android适应图片
用ticons指令结合ImageMagickDisplay工具批量生成Android适应图片 ticons的用法可以百度 这里记录下具体的编译方法 在安装了ticons和ImageMagickDisp ...
- PHP 批量生成静态文件目录代码
<?php /** * @author:jiangzaixing 20160314 * 获取静态文件方法 */ class StaticFile { const MAP_FILE_NAME = ...
- 将表里的数据批量生成INSERT语句的存储过程 继续增强版
文章继续 桦仔兄的文章 将表里的数据批量生成INSERT语句的存储过程 增强版 继续增强... 本来打算将该内容回复于桦仔兄的文章的下面的,但是不知为何博客园就是不让提交!.... 所以在这里贴出来吧 ...
随机推荐
- Request.Url.Port 获取不到正确的端口号
今天遇到一个很奇怪的事情,用request.url.port来获取一个请求的端口,返回是80 ,很纳闷啊我的请求上面是http://www.XX.com:8088 啊,怎么会是80啊,太不可思议了! ...
- FreeRTOS+FreeModbus+神舟IV号
下面的这个例子是FreeModbus和FreeRTOS在神舟IV号上的应用,仅当做学习用途. 这个demo完成的功能也比较简单,创建了两个任务,一个任务用于控制板子上的LED1,使它每1秒钟闪烁一次. ...
- source insight研究——快捷键篇
转:http://blog.csdn.net/ison81/article/details/3510426 关于键盘和鼠标谁更快捷之争,是一个永远被程序员争论的话题.我想大多数人都不会极端的信奉一种操 ...
- Asp.net+EF
EFRepositoryBase using System; using System.Collections.Generic; using System.Data; using System.Dat ...
- VMware报错“原因: 未能锁定文件”,打开失败
原文:http://jingyan.baidu.com/article/425e69e6bf64dbbe15fc16fe.html VMware打开复制的虚拟机,报错“原因: 未能锁定文件”,打开失败 ...
- NoHttp详解之NoHttp最基本使用(无封装)
NoHttp详细使用文档,请点我移步! 这里是一个最基本的使用,在项目中也可以直接这样使用,如果想学习更多请移步NoHttp主页: https://github.com/yanzhenjie/NoHt ...
- ASP.NET MVC学习---(九)权限过滤机制(完结篇)
相信对权限过滤大家伙都不陌生 用户要访问一个页面时 先对其权限进行判断并进行相应的处理动作 在webform中 最直接也是最原始的办法就是 在page_load事件中所有代码之前 先执行一个权限判断的 ...
- 基于WPF系统框架设计(2)-Fluent Ribbon之HelloWorld
Fluent/Ribbon是微软在其最新桌面操作系统Windows 7中使用的图形用户界面. Windows平台的进化,伴随着系统图形界面的重新设计.从Windows XP到Windows Vista ...
- foreach 加& 什么意思?
foreach 加&遍历的同时改变原数组即修改数据或者增加数据 foreach 加& 什么意思? 注意:如果我要改变数组某一个值 直接遍历的话原数组是不会变的 下面提供两种方法 1.我 ...
- js 参数校验器
//校验器 var validate = { //校验当前运行环境是否是手机端 isWap:function(){ var sUserAgent= navigator.userAgent.toLowe ...