首页 > 代码库 > Unity 编辑器扩展 场景视图内控制对象
Unity 编辑器扩展 场景视图内控制对象
假设有一个敌人生成器类,其中有个属性range用来表示敌人生成的范围区域大小,那么可以用OnDrawGizmos函数来绘制它在场景视图所代表的区域大小,便于开发调试。这个敌人生成器类,类似如下:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using UnityEngine; using System.Collections; public class EnemySpawn : MonoBehaviour { public float range; void OnDrawGizmos() { Gizmos.color = Color.green; Gizmos.DrawWireCube(transform.position, new Vector3(range, 0, range)); } void OnDrawGizmosSelected() { Gizmos.color = Color.yellow; Gizmos.DrawWireCube(transform.position, new Vector3(range, 0, range)); } } |
可以在场景视图看到,当未选中改对象时,为绿色边框表示区域大小,当选中时,则为黄色。如下图所示:
未选中:
选中:
选中:
如何直接在场景视图进行调整区域的大小呢,即直接调整range值,而不用在检视器里进行设置。这可以用控制柄来达到,即Handles类。创建一个编辑器扩展类,代码如下:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | using UnityEngine; using UnityEditor; [CustomEditor(typeof(EnemySpawn))] public class EnemySpawnEditor : Editor { void OnSceneGUI() { EnemySpawn enemySpawn = target as EnemySpawn; Vector3 pos = enemySpawn.transform.position; // 计算4个角落 Vector3 v0 = new Vector3(pos.x - enemySpawn.range / 2, pos.y, pos.z - enemySpawn.range / 2); Vector3 v1 = new Vector3(pos.x + enemySpawn.range / 2, pos.y, pos.z + enemySpawn.range / 2); float y = v0.y; Vector3[] corners = new Vector3[4]; corners[0] = new Vector3(v0.x, y, v0.z); corners[1] = new Vector3(v0.x, y, v1.z); corners[2] = new Vector3(v1.x, y, v1.z); corners[3] = new Vector3(v1.x, y, v0.z); // 4个缩放值控制柄 for (int i = 0; i < 4; ++i) { enemySpawn.range = Handles.ScaleValueHandle(enemySpawn.range, corners[i], Quaternion.identity, 1, Handles.SphereCap, 1); Handles.Label(corners[i], i.ToString()); } if (GUI.changed) { EditorUtility.SetDirty(target); } } } |
现在可以在场景视图里看到这个对象边框各有一个球体,进行拉动球体,可以看到区域大小值range进行变化了,如下图所示:
现在用控制柄改变的range值,无法进行撤销,这样就无法进行回滚操作,为其添加撤销功能,代码更改为如下:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | using UnityEngine; using UnityEditor; [CustomEditor(typeof(EnemySpawn))] public class EnemySpawnEditor : Editor { void OnSceneGUI() { EnemySpawn enemySpawn = target as EnemySpawn; Vector3 pos = enemySpawn.transform.position; // 计算4个角落 Vector3 v0 = new Vector3(pos.x - enemySpawn.range / 2, pos.y, pos.z - enemySpawn.range / 2); Vector3 v1 = new Vector3(pos.x + enemySpawn.range / 2, pos.y, pos.z + enemySpawn.range / 2); float y = v0.y; Vector3[] corners = new Vector3[4]; corners[0] = new Vector3(v0.x, y, v0.z); corners[1] = new Vector3(v0.x, y, v1.z); corners[2] = new Vector3(v1.x, y, v1.z); corners[3] = new Vector3(v1.x, y, v0.z); EditorGUI.BeginChangeCheck(); float scaleValue = enemySpawn.range; float newRange = scaleValue; // 4个缩放值控制柄 for (int i = 0; i < 4; ++i) { scaleValue = Handles.ScaleValueHandle(enemySpawn.range, corners[i], Quaternion.identity, 1, Handles.SphereCap, 1); newRange = scaleValue == enemySpawn.range ? newRange : scaleValue; Handles.Label(corners[i], i.ToString()); } if (EditorGUI.EndChangeCheck()) { // 记录对象以便进行撤销 Undo.RecordObject(enemySpawn, "Change Range"); enemySpawn.range = newRange; EditorUtility.SetDirty(target); } } } |
现在再次进行拉动,即可在Edit→Undo下看到撤销信息了,如下图所示:
对其他人来讲,可能看到这些球体,不知道是可以拖动的,也不明白拖动它之后会产生什么样的效果,那么,如果能够在鼠标移动到球体上面的时候,能够提示出这些信息就好了。这里,增加下鼠标在球体上时,鼠标箭头会变化成带缩放提示的图标,代码更改为如下:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | using UnityEngine; using UnityEditor; [CustomEditor(typeof(EnemySpawn))] public class EnemySpawnEditor : Editor { void OnSceneGUI() { EnemySpawn enemySpawn = target as EnemySpawn; Vector3 pos = enemySpawn.transform.position; // 计算4个角落 Vector3 v0 = new Vector3(pos.x - enemySpawn.range / 2, pos.y, pos.z - enemySpawn.range / 2); Vector3 v1 = new Vector3(pos.x + enemySpawn.range / 2, pos.y, pos.z + enemySpawn.range / 2); float y = v0.y; Vector3[] corners = new Vector3[4]; corners[0] = new Vector3(v0.x, y, v0.z); corners[1] = new Vector3(v0.x, y, v1.z); corners[2] = new Vector3(v1.x, y, v1.z); corners[3] = new Vector3(v1.x, y, v0.z); EditorGUI.BeginChangeCheck(); float scaleValue = enemySpawn.range; float newRange = scaleValue; float sizeHandle = 1.0f; float realSize = sizeHandle * 0.1f; // 实际为0.15f,比它小才能更精确显示鼠标 // 4个缩放值控制柄 for (int i = 0; i < 4; ++i) { v0 = new Vector3(corners[i].x - realSize, y, corners[i].z - realSize); v1 = new Vector3(corners[i].x + realSize, y, corners[i].z + realSize); // 换算成GUI坐标 Vector2[] handles = new Vector2[4]; handles[0] = HandleUtility.WorldToGUIPoint(new Vector3(v0.x, y, v0.z)); handles[1] = HandleUtility.WorldToGUIPoint(new Vector3(v0.x, y, v1.z)); handles[2] = HandleUtility.WorldToGUIPoint(new Vector3(v1.x, y, v1.z)); handles[3] = HandleUtility.WorldToGUIPoint(new Vector3(v1.x, y, v0.z)); Bounds b = new Bounds(handles[0], Vector3.zero); for (int j = 1; j < 4; ++j) { b.Encapsulate(handles[j]); } Vector2 min = b.min; Vector2 max = b.max; Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); // 调试绘制是否计算正确 Handles.BeginGUI(); GUI.Box(rect, rect.ToString()); Handles.EndGUI(); // 是否鼠标在控制柄上 if (rect.Contains(Event.current.mousePosition)) { // 显示缩放图标的箭头 EditorGUIUtility.AddCursorRect(rect, MouseCursor.ScaleArrow); } scaleValue = Handles.ScaleValueHandle(enemySpawn.range, corners[i], Quaternion.identity, sizeHandle, Handles.SphereCap, 1); newRange = scaleValue == enemySpawn.range ? newRange : scaleValue; Handles.Label(corners[i], i.ToString()); } if (EditorGUI.EndChangeCheck()) { // 记录对象以便进行撤销 Undo.RecordObject(enemySpawn, "Change Range"); enemySpawn.range = newRange; EditorUtility.SetDirty(target); } } } |
这里只是模糊地计算了下球体控制柄的响应范围。现在可以在场景视图看到每个球体都有一个矩形包围着,当鼠标进入到这个矩形里面,就会改变鼠标图形,如下图所示:
现在可以把调试绘制矩形框的给删除掉了,即删除以下代码:
2 3 4 | // 调试绘制是否计算正确 Handles.BeginGUI(); GUI.Box(rect, rect.ToString()); Handles.EndGUI(); |
参考资料:
1.Unity3D研究院之拓展Scene视图(三) http://www.xuanyusong.com/archives/2303
1.Unity3D研究院之拓展Scene视图(三) http://www.xuanyusong.com/archives/2303
2.Unity3D 场景编辑器扩展学习笔记-Handles&Event http://blog.csdn.net/kun1234567/article/details/19477787
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。