Skip to content

Instantly share code, notes, and snippets.

@fumobox
Created March 31, 2021 03:17
Show Gist options
  • Save fumobox/6b6411c0a27693279d8294dd5366ee66 to your computer and use it in GitHub Desktop.
Save fumobox/6b6411c0a27693279d8294dd5366ee66 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public sealed class MeshOptimizerWindow : EditorWindow
{
private GameObject _go;
[MenuItem("Window/PLATEAU Mesh Optimizer")]
public static void ShowWindow()
{
var window = GetWindow<MeshOptimizerWindow>();
window.titleContent = new GUIContent("PLATEAU Mesh Optimizer");
window.position = new Rect(10, 10, 300, 300);
}
public void OnGUI()
{
GUILayout.Label("FBXをインポートしてシーンに置いてからTargetにセットしてください。");
_go = EditorGUILayout.ObjectField("Target", _go, typeof(GameObject)) as GameObject;
if (GUILayout.Button("変換", GUILayout.Height(40)))
{
Debug.Log($"Child Count: {_go.transform.childCount}");
var t0 = Time.realtimeSinceStartup;
var parent = new GameObject(_go.name);
AssetDatabase.StartAssetEditing();
foreach (Transform t in _go.transform)
{
MergeMesh(t, parent.transform);
}
AssetDatabase.StopAssetEditing();
var time = Time.realtimeSinceStartup - t0;
Debug.Log($"Done: {time}sec");
}
}
private void MergeMesh(Transform t, Transform parent)
{
var newMesh = new Mesh();
var vertices = new List<Vector3>();
var indexes = new List<int>();
var uvs = new List<Vector2>();
var index = 0;
Material mat = null;
foreach (Transform child in t)
{
var meshFilter = child.GetComponent<MeshFilter>();
var mesh = meshFilter.mesh;
// FIXME 最後に取得したマテリアルをセットするが、意図したマテリアルになる保証はない。
var meshRenderer = child.GetComponent<MeshRenderer>();
mat = meshRenderer.material;
vertices.AddRange(mesh.vertices);
if (mesh.uv.Length == 0)
{
// UVが無いモデルは0で埋める。
for (var i = 0; i < mesh.vertices.Length; i++)
uvs.Add(Vector2.zero);
}
else
{
uvs.AddRange(mesh.uv);
}
var tris = mesh.triangles;
foreach (var i in tris) indexes.Add(i + index);
index += mesh.vertices.Length;
}
newMesh.vertices = vertices.ToArray();
newMesh.triangles = indexes.ToArray();
newMesh.uv = uvs.ToArray();
newMesh.RecalculateNormals();
CreateObject(newMesh, mat, t.name, parent);
}
// GameObject生成
private void CreateObject(Mesh mesh, Material material, string objName, Transform parent)
{
CreateAsset(mesh, objName, $"{parent.name}/mesh");
CreateAsset(material, objName, $"{parent.name}/material");
var go = new GameObject(objName);
go.transform.localRotation = Quaternion.Euler(-90, 0, 0);
go.transform.SetParent(parent);
var mf = go.AddComponent<MeshFilter>();
mf.sharedMesh = mesh;
var mr = go.AddComponent<MeshRenderer>();
mr.sharedMaterial = material;
}
// アセット生成
private void CreateAsset(Object obj, string assetName, string directory)
{
if (AssetDatabase.Contains(obj)) return;
var dir = Path.Combine(Application.dataPath, directory);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
var fileName = assetName + ".asset";
var path = Path.Combine(Application.dataPath, directory, fileName);
var cnt = 1;
while (File.Exists(path))
{
fileName = $"{assetName} {cnt}.asset";
path = Path.Combine(Application.dataPath, directory, fileName);
cnt++;
}
AssetDatabase.CreateAsset(obj, Path.Combine("Assets", directory, fileName));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment