老樣子先看效果
實現步驟
1.彈窗
效果
代碼
using System; using System.Collections; using System.Collections.Generic; using System.Text; using UnityEditor; using UnityEngine; public class EditVector : EditorWindow { string SavePath = ""; bool FreeMove = true; private void OnGUI() { GUILayout.BeginVertical(); //標簽 GUILayout.BeginHorizontal(); GUILayout.Box("正在編輯頂點...", TitleBoxStyle(), GUILayout.Height(60), GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.Button("選擇源文件夾", GUILayout.Height(30), GUILayout.Width(180))) { SavePath = EditorUtility.OpenFolderPanel("選擇源文件夾", "Assets/", ""); } GUILayout.Space(10); FreeMove=GUILayout.Toggle(FreeMove,"自由拖拽"); GUILayout.BeginHorizontal(); if (GUILayout.Button("保存", GUILayout.Height(30))) { if (SaveEdit()) { instance.Close(); } } GUILayout.Space(10); if (GUILayout.Button("取消", GUILayout.Height(30))) { Reset(); instance.Close(); } GUILayout.Space(10); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } public GUIStyle TitleBoxStyle() { GUIStyle boxStyle = new GUIStyle(); boxStyle.margin = new RectOffset(2, 2, 2, 2); boxStyle.border = new RectOffset(2, 2, 2, 2); boxStyle.fontSize = 25; boxStyle.fontStyle = FontStyle.Bold; boxStyle.alignment = TextAnchor.MiddleCenter; return boxStyle; } }
2.調用彈窗
代碼
public class EditVectorManager { //網格 [MenuItem("GameObject//編輯頂點", false, -1)] static void EditTerrainVector() { EditorWindow ew=EditorWindow.GetWindow<EditVector>(false, "編輯頂點", true); ew.Show(); } }
3.鼠標選擇Scene場景UI
效果:
代碼:
using System; using System.Collections; using System.Collections.Generic; using System.Text; using UnityEditor; using UnityEngine; public class EditVector : EditorWindow { string SavePath = ""; bool FreeMove = true; public static EditVector instance; void OnEnable() { instance = this; SceneView.duringSceneGui -= this.OnSceneGUI; SceneView.duringSceneGui += this.OnSceneGUI; } void OnDisable() { instance = null; SceneView.duringSceneGui -= this.OnSceneGUI; } void OnSceneGUI(SceneView sceneView) { //繪制選擇框 Handles.BeginGUI(); if (starSelectPos != Vector2.zero) { Vector2 difference = mousePos - starSelectPos; difference = new Vector2(Mathf.Abs(difference.x), Mathf.Abs(difference.y)); GUILayout.BeginArea(new Rect(starSelectPos, difference)); GUILayout.Box("", SelectMouesDraw(), GUILayout.Height(difference.y), GUILayout.Width(difference.x)); GUILayout.EndArea(); } Handles.EndGUI(); HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));//替換Uinity自帶的默認控制 SelectVectorGUI(); sceneView.Repaint(); } Vector2 mousePos; Vector2 starSelectPos; /// <summary> /// 檢測輸入 /// </summary> void SelectVectorGUI() { Event e = Event.current; mousePos = e.mousePosition; if (e.type==EventType.MouseDrag&&e.control&&e.button==0) { if (starSelectPos == Vector2.zero) { starSelectPos = new Vector2(mousePos.x, mousePos.y); } isShowSelectVector = false; /// Debug.LogError("開始選擇"); } if (e.type == EventType.MouseUp && e.control && e.button == 0) { starSelectPos=Vector2 .zero; } } private void OnGUI() { GUILayout.BeginVertical(); //標簽 GUILayout.BeginHorizontal(); GUILayout.Box("正在編輯頂點...", TitleBoxStyle(), GUILayout.Height(60), GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.Button("選擇源文件夾", GUILayout.Height(30), GUILayout.Width(180))) { SavePath = EditorUtility.OpenFolderPanel("選擇源文件夾", "Assets/", ""); } GUILayout.Space(10); FreeMove=GUILayout.Toggle(FreeMove,"自由拖拽"); GUILayout.BeginHorizontal(); if (GUILayout.Button("保存", GUILayout.Height(30))) { if (SaveEdit()) { instance.Close(); } } GUILayout.Space(10); if (GUILayout.Button("取消", GUILayout.Height(30))) { Reset(); instance.Close(); } GUILayout.Space(10); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } public GUIStyle TitleBoxStyle() { GUIStyle boxStyle = new GUIStyle(); boxStyle.margin = new RectOffset(2, 2, 2, 2); boxStyle.border = new RectOffset(2, 2, 2, 2); boxStyle.fontSize = 25; boxStyle.fontStyle = FontStyle.Bold; boxStyle.alignment = TextAnchor.MiddleCenter; return boxStyle; } public GUIStyle SelectMouesDraw() { GUIStyle boxStyle = new GUIStyle(); boxStyle.margin = new RectOffset(0, 0, 0, 0); boxStyle.border = new RectOffset(2, 2, 2, 2); boxStyle.padding = new RectOffset(0, 0, 0, 0); boxStyle.alignment = TextAnchor.MiddleCenter; Texture2D img = new Texture2D(1,1); Color[] colorlist = img.GetPixels(); colorlist[0] = new Color(0,1,0,0.3f); img.SetPixels(colorlist); boxStyle.normal.background = img; return boxStyle; } }
4.選擇頂點並編輯
效果:不放了給最上面一致
代碼(即:完整代碼)
using System; using System.Collections; using System.Collections.Generic; using System.Text; using UnityEditor; using UnityEngine; public class EditVector : EditorWindow { string SavePath = ""; bool FreeMove = true; public static EditVector instance; public RaycastHit curHit; public Mesh selectMesh;//網格 MeshCollider selectMeshCollider; GameObject selectObj; Vector3[] selectObjVectors;//用於還原 List<Vector3> selectMeshVectorWPs; List<Vector3> selectedVertex;//選擇的頂點 List<int> selectedVertexIndex;//選擇的頂點的下標 void OnEnable() { instance = this; SceneView.duringSceneGui -= this.OnSceneGUI; SceneView.duringSceneGui += this.OnSceneGUI; selectObj = Selection.activeGameObject; selectMesh =Selection.activeGameObject.GetComponent<MeshFilter>().mesh; selectMeshCollider = Selection.activeGameObject.GetComponent<MeshCollider>(); selectObjVectors = selectMesh.vertices; //獲取游戲物體上的頂點在世界空間的坐標 selectMeshVectorWPs = LocalToWorld(selectMesh.vertices, selectObj.transform); } #region 工具函數 List<Vector3> LocalToWorld(Vector3[] s,Transform objTF) { List<Vector3> vector3s = new List<Vector3>(); foreach (Vector3 i in s) { vector3s.Add(objTF.TransformPoint(i)); } return vector3s; } Vector3[] WorldToLocal(List<Vector3> s, Transform objTF) { Vector3[] vector3s =new Vector3[s.Count]; for (int i=0;i< s.Count;i++) { vector3s[i] = objTF.InverseTransformPoint(s[i]); } return vector3s; } #endregion void OnDisable() { instance = null; SceneView.duringSceneGui -= this.OnSceneGUI; } bool isShowSelectVector = false; void OnSceneGUI(SceneView sceneView) { //繪制選擇框 Handles.BeginGUI(); if (starSelectPos != Vector2.zero) { Vector2 difference = mousePos - starSelectPos; difference = new Vector2(Mathf.Abs(difference.x), Mathf.Abs(difference.y)); GUILayout.BeginArea(new Rect(starSelectPos, difference)); GUILayout.Box("", SelectMouesDraw(), GUILayout.Height(difference.y), GUILayout.Width(difference.x)); GUILayout.EndArea(); } Handles.EndGUI(); Handles.color = Color.green; //處理選擇好的頂點 if (isShowSelectVector) { SelectVertex(sceneView.camera); starSelectPos = Vector2.zero; isShowSelectVector = false; } //繪制選擇的頂點並編輯 if (selectedVertex != null) { Vector3 vtr3=Vector3.zero; Vector3 delta = Vector3.zero; foreach (Vector3 item in selectedVertex) { Vector3 lastVtr = new Vector3(item.x, item.y, item.z); //給選中的點掛載拖動的方法 if (FreeMove) { vtr3=Handles.FreeMoveHandle(lastVtr, Quaternion.identity, 0.005f * sceneView.size, Vector3.zero, Handles.DotCap); } else { vtr3=Handles.PositionHandle(lastVtr, Quaternion.identity); } if(lastVtr!= vtr3)//有點被移動 { delta = vtr3 - lastVtr; break; } } //更新網格 for (int k=0;k< selectedVertexIndex.Count;k++) { selectMeshVectorWPs[selectedVertexIndex[k]] += delta; selectedVertex[k] = selectMeshVectorWPs[selectedVertexIndex[k]]; } selectMesh.vertices= WorldToLocal(selectMeshVectorWPs, selectObj.transform); } HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));//替換Uinity自帶的默認控制 SelectVectorGUI(); sceneView.Repaint(); } /// <summary> /// 選擇頂點 /// </summary> /// <param name="camera"></param> void SelectVertex(Camera camera) { //獲取模型點在屏幕上的位置 List<Vector3> vector3s = new List<Vector3>(); foreach (Vector3 i in selectMeshVectorWPs) { vector3s.Add(camera.WorldToScreenPoint(i)); } //獲取在選取內的模型頂點 float minX = Math.Min(mousePos.x, starSelectPos.x); float maxX = Math.Max(mousePos.x, starSelectPos.x); float minY = Math.Min(mousePos.y, starSelectPos.y); float maxY = Math.Max(mousePos.y, starSelectPos.y); selectedVertex = new List<Vector3>(); selectedVertexIndex = new List<int>(); for (int i=0;i< vector3s.Count;i++) { if (vector3s[i].x>= minX&& vector3s[i].x <= maxX && camera.scaledPixelHeight-vector3s[i].y <= maxY && camera.scaledPixelHeight-vector3s[i].y >= minY )//這里坐標有坑 選區是左上角為原點 實際上是左下角 { selectedVertex.Add(selectMeshVectorWPs[i]); selectedVertexIndex.Add(i); } } } Vector2 mousePos; Vector2 starSelectPos; /// <summary> /// 檢測輸入 /// </summary> void SelectVectorGUI() { Event e = Event.current; mousePos = e.mousePosition; if (e.type==EventType.MouseDrag&&e.control&&e.button==0) { if (starSelectPos == Vector2.zero) { starSelectPos = new Vector2(mousePos.x, mousePos.y); } isShowSelectVector = false; /// Debug.LogError("開始選擇"); } if (e.type == EventType.MouseUp && e.control && e.button == 0) { isShowSelectVector = true; } } #region 保存和取消 void Reset() { if (selectObjVectors != null) { selectMesh.vertices = selectObjVectors; } } bool SaveEdit() { if (SavePath.Equals("")) { Debug.LogError("沒有選擇保存路徑"); return false; } selectMeshCollider.sharedMesh= selectMesh; MeshUtility.Optimize(selectMesh);//優化網格 string savePath = SavePath.Substring(SavePath.IndexOf("Assets")); AssetDatabase.CreateAsset(selectMesh, savePath + "/"+ selectObj.name+ ".asset"); return true; } #endregion private void OnGUI() { GUILayout.BeginVertical(); //標簽 GUILayout.BeginHorizontal(); GUILayout.Box("正在編輯頂點...", TitleBoxStyle(), GUILayout.Height(60), GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); GUILayout.Space(10); if (GUILayout.Button("選擇源文件夾", GUILayout.Height(30), GUILayout.Width(180))) { SavePath = EditorUtility.OpenFolderPanel("選擇源文件夾", "Assets/", ""); } GUILayout.Space(10); FreeMove=GUILayout.Toggle(FreeMove,"自由拖拽"); GUILayout.BeginHorizontal(); if (GUILayout.Button("保存", GUILayout.Height(30))) { if (SaveEdit()) { instance.Close(); } } GUILayout.Space(10); if (GUILayout.Button("取消", GUILayout.Height(30))) { Reset(); instance.Close(); } GUILayout.Space(10); GUILayout.EndHorizontal(); GUILayout.EndVertical(); } public GUIStyle TitleBoxStyle() { GUIStyle boxStyle = new GUIStyle(); boxStyle.margin = new RectOffset(2, 2, 2, 2); boxStyle.border = new RectOffset(2, 2, 2, 2); boxStyle.fontSize = 25; boxStyle.fontStyle = FontStyle.Bold; boxStyle.alignment = TextAnchor.MiddleCenter; return boxStyle; } public GUIStyle SelectMouesDraw() { GUIStyle boxStyle = new GUIStyle(); boxStyle.margin = new RectOffset(0, 0, 0, 0); boxStyle.border = new RectOffset(2, 2, 2, 2); boxStyle.padding = new RectOffset(0, 0, 0, 0); boxStyle.alignment = TextAnchor.MiddleCenter; Texture2D img = new Texture2D(1,1); Color[] colorlist = img.GetPixels(); colorlist[0] = new Color(0,1,0,0.3f); img.SetPixels(colorlist); boxStyle.normal.background = img; return boxStyle; } } public class EditVectorManager { //網格 [MenuItem("GameObject//編輯頂點", false, -1)] static void EditTerrainVector() { EditorWindow ew=EditorWindow.GetWindow<EditVector>(false, "編輯頂點", true); ew.Show(); } }
總結:
基本上核心功能就是這些東西,時間有限很多東西都沒來得及解釋(有時間的話再添加詳細解釋),有不明白的地方可以留言,不對的地方希望大家指正。希望能和大家一起進步!