老样子先看效果

实现步骤
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();
}
}
总结:
基本上核心功能就是这些东西,时间有限很多东西都没来得及解释(有时间的话再添加详细解释),有不明白的地方可以留言,不对的地方希望大家指正。希望能和大家一起进步!
原文:https://www.cnblogs.com/littlebao/p/12387762.html