http://blog.csdn.net/akof1314/article/details/38129031

假设有一个敌人生成器类,其中有个属性range用来表示敌人生成的范围区域大小,那么可以用OnDrawGizmos函数来绘制它在场景视图所代表的区域大小,便于开发调试。这个敌人生成器类,类似如下:

1
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类。创建一个编辑器扩展类,代码如下:
1
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值,无法进行撤销,这样就无法进行回滚操作,为其添加撤销功能,代码更改为如下:
1
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下看到撤销信息了,如下图所示:
 
对其他人来讲,可能看到这些球体,不知道是可以拖动的,也不明白拖动它之后会产生什么样的效果,那么,如果能够在鼠标移动到球体上面的时候,能够提示出这些信息就好了。这里,增加下鼠标在球体上时,鼠标箭头会变化成带缩放提示的图标,代码更改为如下:
1
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);
        }
    }
}

这里只是模糊地计算了下球体控制柄的响应范围。现在可以在场景视图看到每个球体都有一个矩形包围着,当鼠标进入到这个矩形里面,就会改变鼠标图形,如下图所示:
现在可以把调试绘制矩形框的给删除掉了,即删除以下代码:
1
2
3
4
 
// 调试绘制是否计算正确
Handles.BeginGUI();
GUI.Box(rect, rect.ToString());
Handles.EndGUI();
 
参考资料:
1.Unity3D研究院之拓展Scene视图(三) http://www.xuanyusong.com/archives/2303
2.Unity3D 场景编辑器扩展学习笔记-Handles&Event http://blog.csdn.net/kun1234567/article/details/19477787

Unity 编辑器扩展 场景视图内控制对象的更多相关文章

  1. unity编辑器扩展_05(删除游戏对象并具有撤回功能)

    代码: [MenuItem("Tools/Delete",false,1)]    static void Delete()    {        GameObject[] go ...

  2. unity 编辑器扩展简单入门

    unity 编辑器扩展简单入门 通过使用编辑器扩展,我们可以对一些机械的操作实现自动化,而不用使用额外的环境,将工具与开发环境融为一体:并且,编辑器扩展也提供GUI库,来实现可视化操作:编辑器扩展甚至 ...

  3. Unity编辑器扩展chapter1

    Unity编辑器扩展chapter1 unity通过提供EditorScript API 的方式为我们提供了方便强大的编辑器扩展途径.学好这一部分可以使我们学会编写一些工具来提高效率,甚至可以自制一些 ...

  4. Unity编辑器扩展 Chapter7--使用ScriptableObject持久化存储数据

    Unity编辑器扩展 Chapter7--使用ScriptableObject持久化存储数据 unity unity Editor ScirptableObject  Unity编辑器扩展 Chapt ...

  5. Unity编辑器扩展Texture显示选择框

    学习NGUI插件的时候,突然间有一个问题为什么它这些属性可以通过弹出窗口来选中呢? 而我自己写的组件只能使用手动拖放的方式=.=. Unity开发了组件Inspector视图扩展API,如果我们要写插 ...

  6. Unity 编辑器扩展

    自定义检视面板的使用: 先是定义一个脚本文件,我们来修饰它的检视面板: [HelpURL("http://www.baidu.com")] public class Atr : M ...

  7. unity编辑器扩展_06(给选项添加快捷键,控制菜单是否启用)

    代码: [MenuItem("Tools/Delete ", true, 1)]    static bool DeleteVadidate()    {        if (S ...

  8. Unity 编辑器扩展 Chapter2—Gizmos

    二. 使用Gizoms绘制网格及矩阵转换使用 1. 创建Leve类,作为场景控制类: using UnityEngine; //使用namespace方便脚本管理 namespace RunAndJu ...

  9. unity编辑器扩展学习

    扩展编辑器实际上就是在unity菜单栏中添加一些按钮,可以一键执行一些重复性的工作. 一.添加按钮 1.简单使用MenuItem特性 using UnityEngine; using UnityEdi ...

随机推荐

  1. python中的yield生成器详解

    #原创,转载请先联系 在学习生成器之前,必须先了解一下迭代器.因为生成器就是一种特殊的迭代器,而且生成器用起来更加优雅. 迭代器的详解可以参考我的另一篇博文:https://www.cnblogs.c ...

  2. 使用python获取整月每一天的系统监控数据生成报表

    1.安装阿里开源监控工具tsar tsar官方网站 wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-c ...

  3. python 垃圾回收详解

    原文:https://zhuanlan.zhihu.com/p/31150408 总纲 策略和垃圾回收系统工作内容 引用计数详解 标记-清除+分代收集 循环引用 编程应用-常见方法 ex 过程详解 使 ...

  4. 微信小程序保存图片的方法

    1.xhtml代码 长按保存: <view class="img" catchlongpress='baocun'></view> 2.Js代码 baocu ...

  5. KO工作原理及带来的好处

    介绍 Knockout是一个以数据模型(data model)为基础的能够帮助你创建富文本,响应显示和编辑用户界面的JavaScript类库.任何时候如果你的UI需要自动更新(比如:更新依赖于用户的行 ...

  6. 在使用Arduino中遇到的问题(无法使用中文注释、程序无法下载)

    在使用Arduino中遇到的问题: 在用arduino给蓝牙模块供电时,下载程序是下不进去的.即使显示下进去了,其实也是没下进去. 解决方法:拔掉蓝牙模块再下程序,或给蓝牙供电的线上加上一个开关. 在 ...

  7. Jquery获取服务器端控件的三种方式

    一 Jquery获得服务器控件值的方法由于ASP.NET网页运行后,服务器控件会随机生成客户端id,jquery获取时候不太好操作,google了下,总结有以下3种方法: 服务器控件代码:<as ...

  8. HDU 6322.Problem D. Euler Function -欧拉函数水题(假的数论题 ̄▽ ̄) (2018 Multi-University Training Contest 3 1004)

    6322.Problem D. Euler Function 题意就是找欧拉函数为合数的第n个数是什么. 欧拉函数从1到50打个表,发现规律,然后勇敢的水一下就过了. 官方题解: 代码: //1004 ...

  9. POJ 1164 城堡问题【DFS/位运算/种子填充法/染色法】

    1 2 3 4 5 6 7 ############################# 1 # | # | # | | # #####---#####---#---#####---# 2 # # | ...

  10. dutacm.club 1094: 等差区间(RMQ区间最大、最小值,区间GCD)

    1094: 等差区间 Time Limit:5000/3000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Total ...