总调:代码 顶点创建+动态保存mesh资源+材质资源+树形结构复制
无独有偶,unity3d 2d项目用的是SpriteRenderer,因为Laya是无法支持的,所以需要转换成mesh
因为层级缩放会影响物体的大小,还要复制树形结构
如何使用?
选择物体父对象后选择第一个按钮
以后为VIP代码内容,
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class SpritesToMesh : Editor
{
static bool LogTreePath = false;
static NodeListView m_NodeListView = new NodeListView();
/// <summary>
/// 选中对象后通过顶部菜单进行批量转换
/// </summary>
[MenuItem("JieTools/SpritesToMesh")]
static void Do()
{
//获取所有的SpriteRender
var g = Selection.activeGameObject;
var spriteRenderers = new List<SpriteRenderer>();
foreach (Transform t in g.GetComponentsInChildren<Transform>())
{
var sp = t.GetComponent<SpriteRenderer>();
if (sp != null)
{
spriteRenderers.Add(sp);
}
}
var d = g.GetComponent<NodeListView>();
//创建树形结构
foreach (var item in spriteRenderers)
{
CreateTree(item.gameObject);
}
}
[MenuItem("JieTools/SpritesToMesh2")]
static void Do2()
{
var g = Selection.activeGameObject;
GenerateFormSprite(g.GetComponent<SpriteRenderer>(), new GameObject());
}
static void CreateTree(GameObject node)
{
List<NodeData> path = GetFullPath_List(node.transform);
var fullpath = Path2String(path);
if (path != null)
{
Transform parent = null;
// Transform rootTs = null;
for (int i = 0; i < path.Count; i++)
{
if (i == 0)
{
var rootGo = GameObject.Find("Laya_" + path[i]);
if (rootGo == null)
{
parent = new GameObject("Laya_" + path[i]).transform;
}
else
{
parent = rootGo.transform;
}
}
else
{
if (path[i].nodeName == "c")
{
Debug.Log("ddd");
}
var curNode = GetChildExt(parent, path[i].idx);
if (curNode == null)
{
curNode = new GameObject(path[i].nodeName).transform;
// Debug.Log(curNode.name);
curNode.transform.SetParent(parent);
curNode.transform.localPosition = path[i].localPosition;
curNode.transform.localRotation = path[i].localRotation;
curNode.transform.localScale = path[i].localScale;
//curNode.transform.localScale = Vector3.one;
parent = curNode.transform;
// Debug.Log("parent"+parent.name);
//var mat = CreatMatExt(path[i].sp);
//if (mat)
//{
// CreatMesh(curNode.gameObject, mat);
// //4倍缩放才和sprite一致
// //curNode.transform.localScale *= 4;
//}
CreatMatAndMesh(path[i].sp, curNode.gameObject);
}
else
{
parent = curNode.transform;
}
}
}
}
}
static string Path2String(List<NodeData> path)
{
var s = "";
foreach (var item in path)
{
s += item.nodeName + "/";
}
if (LogTreePath)
Debug.Log(s);
var s1 = "";
foreach (var item in path)
{
s1 += item.idx + "/";
}
//Debug.Log(s1);
return s;
}
private static Transform GetChildExt(Transform t, int idx)
{
// Debug.Log(t.name + " " + idx);
for (int i = 0; i < t.childCount; i++)
{
if (i == idx)
return t.GetChild(idx);
}
return null;
}
private static string GetFullPath(UnityEngine.Transform obj)
{
if (obj.parent == null) return obj.name;
var org = obj;
var parent = obj.parent;
var l = new List<Transform>();
l.Add(parent);
while (obj.parent != null)
{
l.Add(obj.parent);
obj = obj.parent;
}
var p = "";
for (int i = l.Count - 1; i > 0; i--)
{
p += l[i].name + "/";
}
p += org.name;
return p;
}
private static List<NodeData> GetFullPath_List(Transform p_node)
{
if (p_node.parent == null) return null;
// var parent = node.parent;
var l = new List<NodeData>();
var n = new NodeData() { nodeName = p_node.name, idx = GetChildIdx(p_node.parent, p_node) };
n.SetTransformInfo(p_node);
l.Add(n);
// Debug.Log(p_node.name);
Transform curNode = p_node.parent;
while (true)
{
if (curNode != null)
{
if (curNode.parent != null)
{
// Debug.Log(curNode.name);
n = new NodeData() { nodeName = curNode.name, idx = GetChildIdx(curNode.parent, curNode) };
n.SetTransformInfo(curNode);
l.Add(n);
curNode = curNode.parent;
}
else
{
n = new NodeData() { nodeName = curNode.name, idx = -1 };
n.SetTransformInfo(curNode);
l.Add(n);
break;
}
}
else
{
break;
}
}
l.Reverse();
return l;
}
static int GetChildIdx(Transform p, Transform obj)
{
for (int i = 0; i < p.childCount; i++)
{
if (p.GetChild(i) == obj) return i;
}
return -1;
}
static void CreatMesh(GameObject sp, Material mat)
{
var ms = sp.AddComponent<MeshRenderer>();
var d = sp.AddComponent<MeshFilter>();
d.mesh = Resources.Load<GameObject>("Quad").GetComponent<MeshFilter>().sharedMesh;
ms.material = mat;
}
static Material CreatMat(SpriteRenderer sp)
{
if (sp && sp.sprite)
{
// Debug.Log(sp.sprite.name);
return CreatMatAsset(sp.sprite.name, sp.color);
}
return null;
}
static Material CreatMatAsset(string name, Color color)
{
//给texture添加一张png图片 图片的路径 图片的类型
//texture = AssetDatabase.LoadAssetAtPath("Assets/Texture/down.png", typeof(Texture2D)) as Texture2D;
//创建mat
//var mat = new Material(Shader.Find("LayaAir3D/Mesh/BlinnPhong"));
//mat的texture
//mat.mainTexture = texture;
//创建的mat材质放到Assets文件夹下
//AssetDatabase.CreateAsset(mat, "Assets/LayaMat/"+ name + ".mat");
var mat = AssetDatabase.LoadAssetAtPath<Material>("Assets/LayaMat/" + name + ".mat");
if (mat == null)
{
AssetDatabase.CopyAsset("Assets/LayaMat/_TrasnsparentMat.mat", "Assets/LayaMat/" + name + ".mat");
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
if (mat == null)
{
mat = AssetDatabase.LoadAssetAtPath<Material>("Assets/LayaMat/" + name + ".mat");
}
else
{
mat.color = color;
}
var texture = AssetDatabase.LoadAssetAtPath<Texture>("Assets/LayaTexture/" + name + ".PNG");
if (texture == null)
{
Debug.LogError("找不到图片" + "Assets/LayaTexture/" + name + ".PNG");
}
mat.SetTexture("_MainTex", texture);
return mat;
}
static void GenerateFormSprite(SpriteRenderer _spriteRenderer, GameObject gameObject)
{
//sprite的三角形数组
ushort[] triangles0 = _spriteRenderer.sprite.triangles;
//mesh的三角形数组
int[] meshTriangles = new int[triangles0.Length];
//mesh的三角形顶点
Vector3[] vertices0 = new Vector3[_spriteRenderer.sprite.vertices.Length];
//存储顶点数组
for (int i = 0; i < _spriteRenderer.sprite.vertices.Length; i++)
{
vertices0[i] = new Vector3(_spriteRenderer.sprite.vertices[i].x, _spriteRenderer.sprite.vertices[i].y, 0);
}
//存储三角形数组
for (int i = 0; i < meshTriangles.Length; i += 3)
{
meshTriangles[i] = triangles0[i];
meshTriangles[i + 1] = triangles0[i + 1];
meshTriangles[i + 2] = triangles0[i + 2];
// yield return new WaitForSeconds(0.02f);
// Debug.DrawLine(vertices0[meshTriangles[i]], vertices0[meshTriangles[i + 1]], Color.red, 100.0f);
//Debug.DrawLine(vertices0[meshTriangles[i + 1]], vertices0[meshTriangles[i + 2]], Color.red, 100.0f);
// Debug.DrawLine(vertices0[meshTriangles[i + 2]], vertices0[meshTriangles[i]], Color.red, 100.0f);
}
//存储sprite的texture
Texture2D texture = _spriteRenderer.sprite.texture;
//生成一个新的物体挂载mesh组件
GameObject go = new GameObject();
MeshFilter meshFilter = go.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = go.AddComponent<MeshRenderer>();
Mesh _mesh = new Mesh();
meshFilter.mesh = _mesh;
//给mesh赋值
_mesh.vertices = vertices0;
_mesh.uv = _spriteRenderer.sprite.uv;
_mesh.triangles = meshTriangles;
//设置物体位置,名字等
go.name = "MeshSprite";
go.transform.position = gameObject.transform.position;
go.transform.localScale = gameObject.transform.localScale;
go.transform.rotation = gameObject.transform.rotation;
//设置mesh的属性
meshRenderer.material = _spriteRenderer.sharedMaterial;
meshRenderer.sharedMaterial.mainTexture = texture;
meshRenderer.sharedMaterial.color = _spriteRenderer.color;
meshRenderer.sortingLayerName = _spriteRenderer.sortingLayerName;
meshRenderer.sortingLayerID = _spriteRenderer.sortingLayerID;
meshRenderer.sortingOrder = _spriteRenderer.sortingOrder;
//销毁原Sprite
DestroyImmediate(gameObject);
AssetDatabase.CreateAsset(meshRenderer.material, "Assets/LayaMatExt/" + _spriteRenderer.sprite.name + ".mat");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
//static void GenerateFormSpriteExt_Backup(SpriteRenderer _spriteRenderer, GameObject gameObject, Material mat)
//{
// //sprite的三角形数组
// ushort[] triangles0 = _spriteRenderer.sprite.triangles;
// //mesh的三角形数组
// int[] meshTriangles = new int[triangles0.Length];
// //mesh的三角形顶点
// Vector3[] vertices0 = new Vector3[_spriteRenderer.sprite.vertices.Length];
// //存储顶点数组
// for (int i = 0; i < _spriteRenderer.sprite.vertices.Length; i++)
// {
// vertices0[i] = new Vector3(_spriteRenderer.sprite.vertices[i].x, _spriteRenderer.sprite.vertices[i].y, 0);
// }
// var d = _spriteRenderer.sprite.bounds;
// //存储三角形数组
// for (int i = 0; i < meshTriangles.Length; i += 3)
// {
// meshTriangles[i] = triangles0[i];
// meshTriangles[i + 1] = triangles0[i + 1];
// meshTriangles[i + 2] = triangles0[i + 2];
// // yield return new WaitForSeconds(0.02f);
// // Debug.DrawLine(vertices0[meshTriangles[i]], vertices0[meshTriangles[i + 1]], Color.red, 100.0f);
// //Debug.DrawLine(vertices0[meshTriangles[i + 1]], vertices0[meshTriangles[i + 2]], Color.red, 100.0f);
// // Debug.DrawLine(vertices0[meshTriangles[i + 2]], vertices0[meshTriangles[i]], Color.red, 100.0f);
// }
// //存储sprite的texture
// Texture2D texture = _spriteRenderer.sprite.texture;
// //生成一个新的物体挂载mesh组件
// //GameObject go = new GameObject();
// MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
// MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
// Mesh _mesh = new Mesh();
// //meshFilter.mesh = _mesh;
// //给mesh赋值
// _mesh.vertices = vertices0;
// _mesh.uv = _spriteRenderer.sprite.uv;
// _mesh.triangles = meshTriangles;
// //设置物体位置,名字等
// // go.name = _spriteRenderer.name;
// var asstMesh = AssetDatabase.LoadAssetAtPath<Mesh>("Assets/LayaMesh/" + texture.name + ".mesh");
// if (asstMesh == null)
// meshFilter.mesh = SaveMeshExt(_spriteRenderer, texture.name);
// else
// {
// meshFilter.mesh = asstMesh;
// }
// //销毁原Sprite
// // DestroyImmediate(gameObject);
// meshRenderer.material = mat;
//}
static void GenerateFormSpriteExt(SpriteRenderer _spriteRenderer, GameObject gameObject, Material mat)
{
//存储sprite的texture
Texture2D texture = _spriteRenderer.sprite.texture;
//生成一个新的物体挂载mesh组件
//GameObject go = new GameObject();
MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = gameObject.AddComponent<MeshRenderer>();
Mesh _mesh = new Mesh();
meshFilter.mesh = _mesh;
var asstMesh = AssetDatabase.LoadAssetAtPath<Mesh>("Assets/LayaMesh/" + texture.name + ".mesh");
if (asstMesh == null)
{
_mesh = UpdateMesh(_spriteRenderer, _mesh, meshFilter);
meshFilter.mesh = SaveMeshExt(_mesh, texture.name);
}
else
{
meshFilter.mesh = asstMesh;
}
//销毁原Sprite
// DestroyImmediate(gameObject);
meshRenderer.material = mat;
}
static void CreatMatAndMesh(SpriteRenderer sp, GameObject obj)
{
if (sp && sp.sprite)
{
// Debug.Log(sp.sprite.name);
GenerateFormSpriteExt(sp, obj, CreatMatAsset(sp.sprite.name, sp.color));
}
}
[MenuItem("JieTools/SaveMesh")]
static void SaveMesh()
{
var g = Selection.activeGameObject;
var _spriteRenderer = g.GetComponent<SpriteRenderer>();
//sprite的三角形数组
ushort[] triangles0 = _spriteRenderer.sprite.triangles;
//mesh的三角形数组
int[] meshTriangles = new int[triangles0.Length];
//mesh的三角形顶点
Vector3[] vertices0 = new Vector3[_spriteRenderer.sprite.vertices.Length];
//存储顶点数组
for (int i = 0; i < _spriteRenderer.sprite.vertices.Length; i++)
{
vertices0[i] = new Vector3(_spriteRenderer.sprite.vertices[i].x, _spriteRenderer.sprite.vertices[i].y, 0);
}
//存储三角形数组
for (int i = 0; i < meshTriangles.Length; i += 3)
{
meshTriangles[i] = triangles0[i];
meshTriangles[i + 1] = triangles0[i + 1];
meshTriangles[i + 2] = triangles0[i + 2];
// yield return new WaitForSeconds(0.02f);
// Debug.DrawLine(vertices0[meshTriangles[i]], vertices0[meshTriangles[i + 1]], Color.red, 100.0f);
//Debug.DrawLine(vertices0[meshTriangles[i + 1]], vertices0[meshTriangles[i + 2]], Color.red, 100.0f);
// Debug.DrawLine(vertices0[meshTriangles[i + 2]], vertices0[meshTriangles[i]], Color.red, 100.0f);
}
Mesh _mesh = new Mesh();
//给mesh赋值
_mesh.vertices = vertices0;
_mesh.uv = _spriteRenderer.sprite.uv;
_mesh.triangles = meshTriangles;
AssetDatabase.CreateAsset(_mesh, "Assets/LayaMesh/1.mesh");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
static Mesh SaveMeshExt_old(SpriteRenderer _spriteRenderer,string name)
{
//sprite的三角形数组
ushort[] triangles0 = _spriteRenderer.sprite.triangles;
//mesh的三角形数组
int[] meshTriangles = new int[triangles0.Length];
//mesh的三角形顶点
Vector3[] vertices0 = new Vector3[_spriteRenderer.sprite.vertices.Length];
//存储顶点数组
for (int i = 0; i < _spriteRenderer.sprite.vertices.Length; i++)
{
vertices0[i] = new Vector3(_spriteRenderer.sprite.vertices[i].x, _spriteRenderer.sprite.vertices[i].y, 0);
}
//存储三角形数组
for (int i = 0; i < meshTriangles.Length; i += 3)
{
meshTriangles[i] = triangles0[i];
meshTriangles[i + 1] = triangles0[i + 1];
meshTriangles[i + 2] = triangles0[i + 2];
// yield return new WaitForSeconds(0.02f);
// Debug.DrawLine(vertices0[meshTriangles[i]], vertices0[meshTriangles[i + 1]], Color.red, 100.0f);
//Debug.DrawLine(vertices0[meshTriangles[i + 1]], vertices0[meshTriangles[i + 2]], Color.red, 100.0f);
// Debug.DrawLine(vertices0[meshTriangles[i + 2]], vertices0[meshTriangles[i]], Color.red, 100.0f);
}
Mesh _mesh = new Mesh();
//给mesh赋值
_mesh.vertices = vertices0;
_mesh.uv = _spriteRenderer.sprite.uv;
_mesh.triangles = meshTriangles;
AssetDatabase.CreateAsset(_mesh, "Assets/LayaMesh/"+ name + ".mesh");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return _mesh;
}
static Mesh SaveMeshExt(Mesh _mesh, string name)
{
AssetDatabase.CreateAsset(_mesh, "Assets/LayaMesh/" + name + ".mesh");
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return _mesh;
}
public static Mesh UpdateMesh(SpriteRenderer spriteRenderer,Mesh mesh,MeshFilter _meshFilter)
{
//Mesh mesh = new Mesh();
//计算Plane大小
Vector2 size;
// size.x = _cellSize.x * _gridSize.x;
// size.y = _cellSize.y * _gridSize.y;
var orglocalScale = spriteRenderer.transform.localScale;
var orgrotation = spriteRenderer.transform.rotation;
spriteRenderer.transform.localScale = Vector3.one;
spriteRenderer.transform.rotation = Quaternion.identity;
var _cellSize = new Vector2(spriteRenderer.bounds.size.x, spriteRenderer.bounds.size.y);
// var _cellSize = new Vector2(1,1);
size = _cellSize;
var _gridSize = new Vector2Int(1, 1);
//计算Plane一半大小
Vector2 halfSize = size / 2;
//计算顶点及UV
List<Vector3> vertices = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
Vector3 vertice = Vector3.zero;
Vector2 uv = Vector3.zero;
for (int y = 0; y < _gridSize.y + 1; y++)
{
//vertice.z = y * _cellSize.y - halfSize.y;//计算顶点Y轴
vertice.z = 0;
// uv.y = y * _cellSize.y / size.y;//计算顶点纹理坐标V
vertice.y = y * _cellSize.y - halfSize.y;
for (int x = 0; x < _gridSize.x + 1; x++)
{
vertice.x = x * _cellSize.x - halfSize.x;//计算顶点X轴
uv.x = x * _cellSize.x / size.x;//计算顶点纹理坐标U
uv.y = y * _cellSize.y / size.y;//计算顶点纹理坐标U
vertices.Add(vertice);//添加到顶点数组
uvs.Add(uv);//添加到纹理坐标数组
}
}
//顶点序列
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int startIndex = 0;
int[] indexs = new int[_gridSize.x * _gridSize.y * 2 * 3];//顶点序列
for (int y = 0; y < _gridSize.y; y++)
{
for (int x = 0; x < _gridSize.x; x++)
{
//四边形四个顶点
a = y * (_gridSize.x + 1) + x;//0
b = (y + 1) * (_gridSize.x + 1) + x;//1
c = b + 1;//2
d = a + 1;//3
//计算在数组中的起点序号
startIndex = y * _gridSize.x * 2 * 3 + x * 2 * 3;
//左上三角形
indexs[startIndex] = a;//0
indexs[startIndex + 1] = b;//1
indexs[startIndex + 2] = c;//2
//右下三角形
indexs[startIndex + 3] = c;//2
indexs[startIndex + 4] = d;//3
indexs[startIndex + 5] = a;//0
}
}
//
mesh.SetVertices(vertices);//设置顶点
mesh.SetUVs(0, uvs);//设置UV
mesh.SetIndices(indexs, MeshTopology.Triangles, 0);//设置顶点序列
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.RecalculateTangents();
_meshFilter.mesh = mesh;
spriteRenderer.transform.localScale = spriteRenderer.transform.localScale;
spriteRenderer.transform.rotation = orgrotation;
return mesh;
}
}
解压密码:280442832_s2m