首页 > 代码库 > Unity 编辑器扩展 场景视图内控制对象
Unity 编辑器扩展 场景视图内控制对象
如果有一个敌人生成器类。当中有个属性range用来表示敌人生成的范围区域大小。那么能够用OnDrawGizmos函数来绘制它在场景视图所代表的区域大小。便于开发调试。这个敌人生成器类,类似例如以下:
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类。创建一个编辑器扩展类,代码例如以下:
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值,无法进行撤销。这样就无法进行回滚操作,为其加入撤销功能,代码更改为例如以下:
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下看到撤销信息了。例如以下图所看到的:
对其它人来讲,可能看到这些球体。不知道是可以拖动的。也不明确拖动它之后会产生什么样的效果,那么,假设可以在鼠标移动到球体上面的时候,可以提示出这些信息就好了。这里,添加下鼠标在球体上时,鼠标箭头会变化成带缩放提示的图标,代码更改为例如以下:
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.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
Unity 编辑器扩展 场景视图内控制对象
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。