Unity中自动展UV小工具
有时候别人给的unity工程中,有些模型是生成的或者是导入时没有展好uv的,非常头疼,又懒得导出到DCC工具去整理uv,所以做了一个简单的展uv的小工具。效果如下:
这里我做了三种展uv的方式:
**1.平面式。**可以选择X\Y\Z平面去进行uv映射,比较适合一些简单的几何体例如墙、地板或者玻璃什么的。
**2.立方体式。**这种比较适合一些比较硬表面的物体,例如桌子、栏杆什么的。这种方式基于Object Space的法线信息去判断该点应该属于哪一个uv平面,所以在面临比较大的曲面会有一些问题,而且我没有做平铺,所以会有一些uv重叠。
**3.使用Lightmap uv。**这一点是我受到红强的启发,我想既然unity可以自动帮我们整理出第二套用于光照贴图的uv,为什么不用呢,所以我就取出光照贴图的uv,去赋予mesh的第一套uv。这个方案的好处是简单省事,而且基本没有uv重叠,适用于所有模型。唯一需要注意的一点是需要在fbx 导入的时候勾选“Generate Lightmap uv”。
最后是代码部分,记得把它放在Assets目录下的Editor文件夹里,规范操作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class unfold : EditorWindow
{
[MenuItem("Gq_Tools/Unfold")]
public static void ShowWin()
{
EditorWindow.CreateInstance<unfold>().Show();
}
private void OnGUI()
{
GUILayout.Space(10);
GUILayout.BeginHorizontal("box");
GUILayout.Space(10);
if (GUILayout.Button("Planar-X unfold"))//UI上画一个按钮
{
//MonoBehaviour.print("do");
Unfold0("X");
}
if (GUILayout.Button("Planar-Y unfold"))//UI上画一个按钮
{
//MonoBehaviour.print("do");
Unfold0("Y");
}
if (GUILayout.Button("Planar-Z unfold"))//UI上画一个按钮
{
//MonoBehaviour.print("do");
Unfold0("Z");
}
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.BeginHorizontal("box");
if (GUILayout.Button("Cubic unfold"))//UI上画一个按钮
{
//MonoBehaviour.print("do");
Unfold1();
}
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayout.BeginHorizontal("box");
if (GUILayout.Button("unfold by lightmap UV"))//UI上画一个按钮
{
//MonoBehaviour.print("do");
Unfold2();
}
GUILayout.EndHorizontal();
}
//Planar Unfold
void Unfold0(string inStr)
{
var objs = Selection.objects;
if (inStr == "X")
{
foreach (var obj in objs)//for每个选中的物体
{
var go = obj as GameObject;
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
Vector3[] vertices = mesh.vertices;
Vector2[] uvs = new Vector2[vertices.Length];
//Planar Unfold
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2( vertices[i].y, vertices[i].z);
}
mesh.uv = uvs;
}
}
if (inStr == "Y")
{
foreach (var obj in objs)//for每个选中的物体
{
var go = obj as GameObject;
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
Vector3[] vertices = mesh.vertices;
Vector2[] uvs = new Vector2[vertices.Length];
//Planar Unfold
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x,vertices[i].z);
}
mesh.uv = uvs;
}
}
if (inStr == "Z")
{
foreach (var obj in objs)//for每个选中的物体
{
var go = obj as GameObject;
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
Vector3[] vertices = mesh.vertices;
Vector2[] uvs = new Vector2[vertices.Length];
//Planar Unfold
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(vertices[i].x, vertices[i].y);
}
mesh.uv = uvs;
}
}
}
//Cubic Unfold
void Unfold1()
{
var objs = Selection.objects;
foreach (var obj in objs)//for每个选中的物体
{
var go = obj as GameObject;
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
Vector3[] vertices = mesh.vertices;
Vector2[] uvs = new Vector2[vertices.Length];
Vector3[] normals = mesh.normals;
//Cubic Unfold
for (int i = 0; i < normals.Length; i++)
{
//X-Plane
if (Mathf.Abs(normals[i].x) > Mathf.Abs(normals[i].y) && Mathf.Abs(normals[i].x) > Mathf.Abs(normals[i].z))
{
uvs[i] = new Vector2(vertices[i].y, vertices[i].z);
}
//Y-Plane
if (Mathf.Abs(normals[i].y) > Mathf.Abs(normals[i].x) && Mathf.Abs(normals[i].y) > Mathf.Abs(normals[i].z))
{
uvs[i] = new Vector2(vertices[i].x, vertices[i].z);
}
//Z-Plane
if (Mathf.Abs(normals[i].z) > Mathf.Abs(normals[i].x) && Mathf.Abs(normals[i].z) > Mathf.Abs(normals[i].y))
{
uvs[i] = new Vector2(vertices[i].x, vertices[i].y);
}
}
mesh.uv = uvs;
}
}
//use lightmap UV
void Unfold2()
{
var objs = Selection.objects;
foreach (var obj in objs)//对于每个选中的物体
{
var go = obj as GameObject;
Mesh mesh = go.GetComponent<MeshFilter>().sharedMesh;
mesh.uv = mesh.uv2;
}
}
}