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. synchronized 修饰static方法

    •1.依靠对象锁锁定 初始化一个对象时,自动有一个 对象锁. synchronized {普通方法}依靠对象锁工作,多线程访问synchronized方法,一旦某个进程抢得锁之后,其他的进程只有排队对 ...

  2. lucene 排序

    (1)排序对一个文档里什么域都没存储,使用字符串排序会排在首位 (2)排序对一个文档里什么域都没存储,使用数字类型排序会默认给其赋值为0进行排序 (3)我们可以对数字类型的null值的文档进行代码控制 ...

  3. hdu 5186(模拟)

    zhx's submissions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  4. 实现类似微信聊天功能的mysql表设计

    前言: 最近设计了一套聊天功能,此功能支持人对人聊天.发送图片.查看聊天记录.按时间展示聊天列表.最后一条聊天数据及未读消息数 下面分享一下表结构及实现逻辑: 表结构: 1.聊天主表 id(主键id) ...

  5. centos7.2使用yum安装MariaDB10.1

    ①添加MariaDB的yum源 1.创建MariaDB.repo sudo vi /etc/yum.repos.d/Mariadb.repo 2.将以下文件中的字段添加到MariaDB.repo文件中 ...

  6. 【cocos2d-js官方文档】十七、事件分发机制

    简介http://blog.csdn.net/qinning199/article/details/41951517 游戏开发中一个很重要的功能就是交互,如果没有与用户的交互,那么游戏将变成动画,而处 ...

  7. 解决nextjs部署到now上之后出现的“Unable to import module 'now__launcher'”错误

    解决nextjs部署到now上之后出现的“Unable to import module 'now__launcher'”错误 这个错误是由于在next.config.js中直接引用了withLess ...

  8. Codeforces #447 Div2 E

    #447 Div2 E 题意 给出一个由有向边构成的图,每条边上有蘑菇,假设有 \(n\) 个蘑菇,那么第一次走过这条边可以获得 \(n\) 个蘑菇,第二次 \(n-1\),第三次 \(n-1-2\) ...

  9. 生成唯一code

    private String getCode() { List<String> ptypeCodeList = mapper.findCodeList(); String code = & ...

  10. Flex页面跳转的五种实现方式

    Flex页面跳转有很多值得学习的地方,本文向大家介绍一下Flex页面跳转的几种方式,主要包括五种方式,这里为大家一一介绍. AD:   在学习Flex的过程中,你可能会遇到Flex页面跳转的概念,这里 ...