139 lines
6.3 KiB
C#
139 lines
6.3 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace Code.Scripts.Gameplay.Utils
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
|
|||
|
|
public class LTCombie : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
private Mesh _CreateMeshFromSubMesh(Mesh sourceMesh, int subMeshIndex)
|
|||
|
|
{
|
|||
|
|
// 创建一个新的网格
|
|||
|
|
Mesh newMesh = new Mesh();
|
|||
|
|
|
|||
|
|
var subMeshDescriptor = sourceMesh.GetSubMesh(subMeshIndex);
|
|||
|
|
|
|||
|
|
// 获取来源网格的顶点、法线、切线和UV数组
|
|||
|
|
Vector3[] vertices = sourceMesh.vertices;
|
|||
|
|
Vector3[] normals = sourceMesh.normals;
|
|||
|
|
Vector4[] tangents = sourceMesh.tangents;
|
|||
|
|
Vector2[] uv = sourceMesh.uv;
|
|||
|
|
|
|||
|
|
// 从来源网格中获取指定子网格的三角形索引数组
|
|||
|
|
int[] triangles = sourceMesh.GetTriangles(subMeshIndex);
|
|||
|
|
|
|||
|
|
// 根据子网格描述符中的顶点数量,创建新网格的顶点、法线、切线和UV数组
|
|||
|
|
Vector3[] newVertices = new Vector3[subMeshDescriptor.vertexCount];
|
|||
|
|
Vector3[] newNormals = new Vector3[subMeshDescriptor.vertexCount];
|
|||
|
|
Vector4[] newTangents = new Vector4[subMeshDescriptor.vertexCount];
|
|||
|
|
Vector2[] newUV = new Vector2[subMeshDescriptor.vertexCount];
|
|||
|
|
|
|||
|
|
// 根据子网格描述符中的三角形索引数量,创建新网格的三角形索引数组
|
|||
|
|
int[] newTriangles = new int[triangles.Length];
|
|||
|
|
|
|||
|
|
// 从来源网格的数组中复制数据到新网格的数组
|
|||
|
|
for (int i = 0; i < subMeshDescriptor.vertexCount; i++)
|
|||
|
|
{
|
|||
|
|
newVertices[i] = vertices[subMeshDescriptor.firstVertex + i];
|
|||
|
|
newNormals[i] = normals[subMeshDescriptor.firstVertex + i];
|
|||
|
|
newTangents[i] = tangents[subMeshDescriptor.firstVertex + i];
|
|||
|
|
newUV[i] = uv[subMeshDescriptor.firstVertex + i];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (int i = 0; i < subMeshDescriptor.indexCount; i++)
|
|||
|
|
{
|
|||
|
|
newTriangles[i] = triangles[i] - subMeshDescriptor.firstVertex;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置新网格的顶点、法线、切线和UV数组,以及三角形索引数组
|
|||
|
|
newMesh.vertices = newVertices;
|
|||
|
|
newMesh.normals = newNormals;
|
|||
|
|
newMesh.tangents = newTangents;
|
|||
|
|
newMesh.uv = newUV;
|
|||
|
|
newMesh.triangles = newTriangles;
|
|||
|
|
|
|||
|
|
return newMesh;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
[ContextMenu("ManualCombine")]
|
|||
|
|
public void ManualCombine()
|
|||
|
|
{
|
|||
|
|
// combine branch
|
|||
|
|
{
|
|||
|
|
var allMeshRenders = GetComponentsInChildren<MeshRenderer>();
|
|||
|
|
var material = allMeshRenders[0].sharedMaterials[0];
|
|||
|
|
var combineInstanceArrays = new CombineInstance[allMeshRenders.Length];
|
|||
|
|
for (var i = 0; i < allMeshRenders.Length; i++)
|
|||
|
|
{
|
|||
|
|
var meshFilter = allMeshRenders[i].GetComponent<MeshFilter>();
|
|||
|
|
var getMesh = meshFilter.sharedMesh;
|
|||
|
|
combineInstanceArrays[i].mesh = _CreateMeshFromSubMesh(getMesh, 0);
|
|||
|
|
combineInstanceArrays[i].transform = meshFilter.transform.localToWorldMatrix;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var newMesh = new Mesh();
|
|||
|
|
newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
|
|||
|
|
newMesh.CombineMeshes(combineInstanceArrays, true, true);
|
|||
|
|
var newGameObject = new GameObject("CombinedMesh_branch");
|
|||
|
|
var newMeshFilter = newGameObject.AddComponent<MeshFilter>();
|
|||
|
|
newMeshFilter.sharedMesh = newMesh;
|
|||
|
|
var newMeshRenderer = newGameObject.AddComponent<MeshRenderer>();
|
|||
|
|
newMeshRenderer.sharedMaterial = material;
|
|||
|
|
newGameObject.transform.localPosition = Vector3.zero;
|
|||
|
|
newGameObject.transform.localRotation = Quaternion.identity;
|
|||
|
|
newGameObject.transform.localScale = Vector3.one;
|
|||
|
|
|
|||
|
|
// transform.gameObject.SetActive(false);
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
// save mesh to asset
|
|||
|
|
UnityEditor.AssetDatabase.CreateAsset(newMesh, "Assets/CombinedMesh_branch.asset");
|
|||
|
|
UnityEditor.AssetDatabase.SaveAssets();
|
|||
|
|
// save prefab to asset
|
|||
|
|
UnityEditor.PrefabUtility.SaveAsPrefabAsset(newGameObject, "Assets/CombinedMesh_branch.prefab");
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// combine trunk
|
|||
|
|
{
|
|||
|
|
var allMeshRenders = GetComponentsInChildren<MeshRenderer>();
|
|||
|
|
var material = allMeshRenders[0].sharedMaterials[1];
|
|||
|
|
var combineInstanceArrays = new CombineInstance[allMeshRenders.Length];
|
|||
|
|
for (var i = 0; i < allMeshRenders.Length; i++)
|
|||
|
|
{
|
|||
|
|
var meshFilter = allMeshRenders[i].GetComponent<MeshFilter>();
|
|||
|
|
var getMesh = meshFilter.sharedMesh;
|
|||
|
|
combineInstanceArrays[i].mesh = _CreateMeshFromSubMesh(getMesh, 1);
|
|||
|
|
combineInstanceArrays[i].transform = meshFilter.transform.localToWorldMatrix;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var newMesh = new Mesh();
|
|||
|
|
newMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
|
|||
|
|
newMesh.CombineMeshes(combineInstanceArrays, true, true);
|
|||
|
|
var newGameObject = new GameObject("CombinedMesh_trunk");
|
|||
|
|
var newMeshFilter = newGameObject.AddComponent<MeshFilter>();
|
|||
|
|
newMeshFilter.sharedMesh = newMesh;
|
|||
|
|
var newMeshRenderer = newGameObject.AddComponent<MeshRenderer>();
|
|||
|
|
newMeshRenderer.sharedMaterial = material;
|
|||
|
|
newGameObject.transform.localPosition = Vector3.zero;
|
|||
|
|
newGameObject.transform.localRotation = Quaternion.identity;
|
|||
|
|
newGameObject.transform.localScale = Vector3.one;
|
|||
|
|
|
|||
|
|
|
|||
|
|
#if UNITY_EDITOR
|
|||
|
|
// save mesh to asset
|
|||
|
|
UnityEditor.AssetDatabase.CreateAsset(newMesh, "Assets/CombinedMesh_trunk.asset");
|
|||
|
|
UnityEditor.AssetDatabase.SaveAssets();
|
|||
|
|
// save prefab to asset
|
|||
|
|
UnityEditor.PrefabUtility.SaveAsPrefabAsset(newGameObject, "Assets/CombinedMesh_trunk.prefab");
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
transform.gameObject.SetActive(false);
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|