using UnityEngine; using System.Collections.Generic; using UnityEditor; [CustomEditor(typeof(SceneBlockDivide))] public class SceneBlockDivideEditor : Editor { private const string rootFormat = "Root_{0} ({1}, {2})"; private const string multiMaterialRoot = "MultipleMaterials"; private SceneBlockDivide mTarget; private int mLastBlockWidth; private Rect mapRect; private MonoScript script; private void OnEnable() { mTarget = (SceneBlockDivide)target; script = MonoScript.FromMonoBehaviour(mTarget); mLastBlockWidth = Mathf.Max(1, mTarget.blockWidth); RefreshSceneSize(); } public override void OnInspectorGUI() { script = EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false) as MonoScript; mTarget.blockWidth = EditorGUILayout.IntField("Block Width", mTarget.blockWidth); if (mTarget.blockWidth >= 1 && mTarget.blockWidth != mLastBlockWidth) mLastBlockWidth = mTarget.blockWidth; var widthTiles = Mathf.CeilToInt(mapRect.width / mLastBlockWidth); var heightTiles = Mathf.CeilToInt(mapRect.height / mLastBlockWidth); EditorGUILayout.LabelField(string.Format("Width: {0}", widthTiles)); EditorGUILayout.LabelField(string.Format("Height: {0}", heightTiles)); if (GUILayout.Button("Refresh Scene", GUILayout.Width(100f))) RefreshSceneSize(); GUILayout.Space(10f); if (GUILayout.Button("Divide Blocks", GUILayout.Width(100f))) { var meshRenderers = GetMeshRenderers(); for (int i = 0; i < meshRenderers.Length; i++) { var multiShaders = false; var meshRenderer = meshRenderers[i]; if (meshRenderer.sharedMaterials.Length > 1) { // 如果多个材质是同一个Shader,则视为普通物体,否则视为特殊物体 for (int j = 1; j < meshRenderer.sharedMaterials.Length; j++) { if (meshRenderer.sharedMaterials[j - 1].shader != meshRenderer.sharedMaterials[j].shader) { multiShaders = true; break; } } } if (multiShaders) { var root = GetRoot(multiMaterialRoot, 0, 0); meshRenderer.transform.SetParent(root); } else { var x = Mathf.FloorToInt((meshRenderer.bounds.min.x - mapRect.min.x) / mLastBlockWidth); var z = Mathf.FloorToInt((meshRenderer.bounds.min.z - mapRect.min.y) / mLastBlockWidth); var root = GetRoot(meshRenderer.sharedMaterial.shader.name, x, z); meshRenderer.transform.SetParent(root); } } } } private void RefreshSceneSize() { var meshRenderers = GetMeshRenderers(); if (meshRenderers.Length == 0) mapRect = new Rect(); else { var bounds = meshRenderers[0].bounds; for (int i = 1; i < meshRenderers.Length; i++) bounds.Encapsulate(meshRenderers[i].bounds); mapRect = new Rect(bounds.min.x, bounds.min.z, bounds.size.x, bounds.size.z); } } private MeshRenderer[] GetMeshRenderers() { var meshRenderers = Object.FindObjectsOfType(); var meshRenderList = new List(); for (int i = 0; i < meshRenderers.Length; i++) { if (meshRenderers[i].gameObject.tag != "SkyBox") meshRenderList.Add(meshRenderers[i]); } return meshRenderList.ToArray(); } private static Transform GetRoot(string name, int x, int z) { var rootName = string.Format(rootFormat, name, x, z); var rootObj = GameObject.Find(rootName); if (rootObj == null) { rootObj = new GameObject(rootName); rootObj.transform.localPosition = Vector3.zero; rootObj.transform.localRotation = Quaternion.identity; rootObj.transform.localScale = Vector3.one; } return rootObj.transform; } }