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语句的存储过程 增强版 继续增强... 本来打算将该内容回复于桦仔兄的文章的下面的,但是不知为何博客园就是不让提交!.... 所以在这里贴出来吧 ...
随机推荐
- 死磕 Fragment 的生命周期
死磕 Fragment 的生命周期 本文原创,转载请注明出处.欢迎关注我的 简书 ,关注我的专题 Android Class 我会长期坚持为大家收录简书上高质量的 Android 相关博文.本篇文章已 ...
- 使用Python3解压gz、tar、tgz、zip、rar五种格式的压缩文件例子
使用Python3解压如下五种压缩文件:gz.tar.tgz.zip.rar 简介 gz: 即gzip,通常只能压缩一个文件.与tar结合起来就可以实现先打包,再压缩. tar: linux系统下的打 ...
- [置顶]
使用kube-proxy让外部网络访问K8S service的ClusterIP
配置方式 kubernetes版本大于或者等于1.2时,外部网络(即非K8S集群内的网络)访问cluster IP的办法是: 修改master的/etc/kubernetes/proxy,把KUBE_ ...
- php安装扩展步骤(redis)
星哥让装一个扩展,解决PDF抓PNG的问题,功能没有实现,有点小悲伤,但是还是学到点东西的. php安装扩展步骤(以redis为例) 前提注意:在自己的LINUX本机上一定要安装有redis软件,我之 ...
- 在CcentOS系统上将deb包转换为rpm包
deb文件格式本是ubuntu/debian系统下的安装文件,那么我想要在redhat/centos/fedora中安装,需要把deb格式的软件包转化成rpm格式. 需要用到的转换工具:alien_8 ...
- php不重新编译添加模块
php不重新编译添加模块 本文以安装mysqli模块为例 一.检查 1:首先保证php-fpm能正常启动 2:查看当前已安装的php模块是否有mysqli [root@web01 ~]# /appli ...
- fmt标签的格式化日期使用
声明: <%@ taglib prefix="fmt" uri="/WEB-INF/fmt.tld" %> or <%@ taglib pre ...
- json-server模拟接口获取mock数据
转载:http://blog.csdn.net/stevennest/article/details/76167343 安装json-server 运行以下命令 cnpm install json-s ...
- Win7旗舰版+IIS7没有错误提示怎么办
在IIS Manger中将ASP的调试属性修改默认值,启用服务端调试和客户端调试都改为True,重启后生效.
- npm -D -S -g -i 以及安装技巧
繁杂:npm install webpack 简洁:npm i webpack 重复性操作: npm i webpack npm i babel-core .... 简洁性操作: npm i webp ...