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. admin管理工具

    admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLE ...

  2. "个性化空间"性能优化方案设计初步

    一.问题的提出 在九月中开始,我们要打造个性化空间,领导要求的是只进行原型的设计,逻辑的设计,不进行技术开发.其实是严重不正确的,因为个性化空间其特点与现有的技术模型完全不同,现有的技术方案未必能适应 ...

  3. c#读取LOG文件并解决读取提示被其他进程占用问题

    c# 读写文件时文件正由另一进程使用,因此该进程无法访问该文件,在IO处理上遇到了无法操作的问题. 文件“C:\u_ex.log”正由另一进程使用,因此该进程无法访问该文件. u_ex.log是一个日 ...

  4. gaggd

    ####算法一 暴力枚举所有可能的$a_2$并递推判断.复杂度$O(r \times k)$,预期得分10分. ####算法二 $a_k$可以表示为$a_1$与$a_2$的线性组合.使用递推计算出系数 ...

  5. PowerDesigner用例图展示设置

    powerdesigner用例图显示设置 powerdesigner中的绘图功能真是不敢恭维,折线半天弄不直,直线半天弄不弯. 1.修改显示设置 tools-->display preferen ...

  6. 2017中国大学生程序设计竞赛 - 女生专场C【前后缀GCD】

    C HDU - 6025 [题意]:去除数列中的一个数字,使去除后的数列中所有数字的gcd尽可能大. [分析]: 数组prefixgcd[],对于prefixgcd[i]=g,g为a[0]-a[i]的 ...

  7. noi题库 1.7 字符串

    前九题 01:统计数字字符个数 总时间限制: 1000ms 内存限制: 65536kB 描述 输入一行字符,统计出其中数字字符的个数. 输入 一行字符串,总长度不超过255. 输出 输出为1行,输出字 ...

  8. Linux查看内核信息或系统信息

    先说说为什么会写这个.这是我去面试的时候面试官问的一个问题,我感觉是一个普遍会被问到的问题.为了让我自己记住,也便于收集下Linux运维方向考官的题目. 第一,查看内核信息 cat /proc/ver ...

  9. JavaScript中的局部作用域及常量的定义

    局部作用域 通常JavaScript的作用域是函数内部,在类似for循环的语句块中是无法申明局部变量的. function exm() { for (var i=0; i<100; i++) { ...

  10. 【二分答案】【Heap-Dijkstra】bzoj2709 [Violet 1]迷宫花园

    显然最短路长度随着v的变化是单调的,于是可以二分答案,据说spfa在网格图上表现较差. #include<cstdio> #include<cstring> #include& ...