老樣子先看效果

實現步驟
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();
}
}
總結:
基本上核心功能就是這些東西,時間有限很多東西都沒來得及解釋(有時間的話再添加詳細解釋),有不明白的地方可以留言,不對的地方希望大家指正。希望能和大家一起進步!
