开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

教程分享

关注:762

当前位置:游戏蛮牛 技术专区 教程分享

查看: 367|回复: 5

[系列教程] Unity编辑器入门201854EditorWindow

[复制链接]  [移动端链接]
回帖奖励 18 蛮牛币 回复本帖可获得 2 蛮牛币奖励! 每人限 1 次(中奖概率 70%)
排名
10337
昨日变化
271

12

主题

54

帖子

325

积分

Rank: 9Rank: 9Rank: 9

UID
215257
好友
1
蛮牛币
1265
威望
0
注册时间
2017-3-29
在线时间
153 小时
最后登录
2018-5-24

迈向小康

发表于 2018-5-4 17:25:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 m2675 于 2018-5-4 18:07 编辑

有写得不好的地方或者写错的地方,希望评论指出来。
继承于EditorWindow的类的回调方法需要在窗口打开的情况下才可以使用。

例如
[C#] 纯文本查看 复制代码
Class TestWindow : EditorWindow

{

       void Awake() { Debug.Log(“Test”);  }

}


里面的Awake方法需要在窗口打开的情况下才调用。

那么如何打开窗口呢,欢迎补充。

第一种也是很多插件里面打开窗体时的常用方法。这样在菜单栏就多出来一栏MyWindow,点击子菜单的TestWindow就能打开窗体了,这个方法得设置为静态方法。
[C#] 纯文本查看 复制代码
[MenuItem("MyWindow/TestWindow")][/align][align=left]  static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(MyFirstWindow));
    }
[/align][align=left]





  另外添加几种快捷键的方式比如[MenuItem("MyTools/ShortcutKey %g")] 代表着Ctrl+G运行 %代表Ctrl &代表ALT #代表Shift

或者是在类里面定义一个公有的初始化方法。例如
[C#] 纯文本查看 复制代码
public void Init()
{
//Show()是EditorWindow类中的方法
Show();
}

然后在其他类的方法中创建对它的引用,然后调用Init方法就好了这里也是一个不容易找到的类
[C#] 纯文本查看 复制代码
public class UnityTest : AssetPostprocessor
{

    //在纹理导入之后调用
        void OnPostprocessTexture(Texture2D texture)
    {
       
            ConvertWindow convertSettings = EditorWindow.CreateInstance<ConvertWindow>();
            convertSettings.Init();
        }
    }


上面的ConvertWindow就是我们继承于EditorWindow的那个类,而本类的父类是一个检测导入的工具类.OnPostprocessTexture(Texture2D texture)方法是在任何Texture2D的图片被导入到Unity之后调用。将窗体打开方法放入这个方法中便可以在导入图片时弹出窗体。




之后便开始讲如何写自己的窗体吧。第一步就是给自己的窗体命名了。
可以用构造方法来命名。
[AppleScript] 纯文本查看 复制代码
public class MyFirstWindow : EditorWindow
{
    
    MyFirstWindow()
    {
        this.titleContent = new GUIContent("Cloud");
    }}


也可以在静态方法构造窗体的时候命名。
JOYEXT7CVYN%O8EJ4C@EA3L.png


或者还有更多命名方式的话   以后再补充好了。

接着开始绘制窗口啦
又要开始用恶心的OnGUI了,最开始接触Unity的时候,UGUI还没出,那时候就OnGUI画框框。过了这么久又回到了它这儿。不过OnGUI的性能据说比NGUI和UGUI好太多。
首先记得强制重绘一下界面   this.Repaint();作用之后会讲到,如果我不鸽的话。
绘制窗口的那些API上一节讲了很多了,综合别人的教程也能看得很明白。无非是需要什么功能就加什么控件上去。
这里另外写一个东西Selection类,Selection类表示当前所选择的物体,无论是Scene还是Hierarchy或者是project中的都可以。
[C#] 纯文本查看 复制代码
GameObject gameObject = Selection.activeGameObject;
                GameObject[] gameObjects = Selection.gameObjects;
                Object[] objects = Selection.objects;
gameObject表示当前选择的GameObject,
gameObjects表示当前选择的多个GameObject,Objects表示当前选择的多个Objects。注意在使用它的时候注意加类型判断,否则会报错。如果不清楚类型的话,建议统一用Object。
[C#] 纯文本查看 复制代码
Selection.objects[0].GetType().ToString() != "UnityEngine.Texture2D"



忘记说Button了。
[C#] 纯文本查看 复制代码
 if (GUILayout.Button("我是名字")){ ShowNotification(new GUIContent("我是提示信息~~"));}
当然 Button也可以F12看看怎么定义的,跟着提供的API自己去画Button吧。
里面的ShowNotification方法是EditorWindow类的方法,具体可以F12自己看看,至于GUIContent是干嘛的呢,百度吧,我没怎么用过。

一些回调方法

Editor不知道有没有这几个方法,但是我用Editor类都是学习,没做出过东西,所以接触不多。
[C#] 纯文本查看 复制代码
  void OnHierarchyChange()
    {
        if (FindObjectOfType<Animation>())
        {
            DestroyImmediate(FindObjectOfType<Animation>());
        }
    }

    private void OnInspectorUpdate()
    {
        Debug.Log("sds");
        if (Input.GetMouseButtonDown(0)) { Debug.Log("asdasdasdas"); }
            
       
        //这个方法里面Debug可以一直运行,但是检测Input无用,待解决。
    }

    void OnProjectChange()
    {
        Debug.Log("Project视图中的资源发生改变时调用一次");
    }



    void OnSelectionChange()
    {
      
      
        if (Selection.objects.Length == 0 || Selection.objects[0].GetType().ToString() != "UnityEngine.GameObject")
            return;
        
        g = Selection.gameObjects[0];
        if (g.GetComponents<Component>().Length >=1 && g.GetComponents<Component>()[1].GetType() == typeof(DragRotate))
        {
            quaternion = g.transform.eulerAngles;
        }

       
        if (g.GetComponent<Camera>())
        {
            mainCamera = g.GetComponent<Camera>();
        }
      

    }

    void OnDestroy()
    {
        Debug.Log("关闭时调用");
    }



OnHierarchyChange()  这个方法在层级面板改变时调用,我用来保证整个项目中没有某个组件,所以每次添加之后就检测一遍,有的话就删除。
OnInspectorUpdate() 这个方法被我当做Update用的,也确实在窗口打开界面会持续调用,只是每一次调用的时间没有Update那么短而已,感兴趣的可以自己试试,但是本想用它来实现快捷键功能,发现Input写上去了之后不报错但是没反应,先放在这里吧,今天搞了个插件,里面有这个功能,等我把那一千多行代码看完了就会了。

OnProjectChange()  当Project中有变化时调用,不知道有没有什么东西可以获取到变化信息,但是目前对这个没有刚需,没研究。
OnSelectionChange() 当选择的物体有改变时调用。


还发现了一个委托
[C#] 纯文本查看 复制代码
 private void OnEnable()
    {
        SceneView.onSceneGUIDelegate += SceneGUI;
    }

    private void OnDisable()
    {
        SceneView.onSceneGUIDelegate -= SceneGUI;
        
    }[/font][/font][/font][/font][/font][/size][/font][/font][/color][/size][size=5][color=Black][font=新宋体][font=新宋体][size=4][font=新宋体][font=新宋体][font=新宋体][font=新宋体][font=新宋体]
[/font][/font][/font][/font][/font][/size][/font][/font][/color][/size][size=5][color=Black][font=新宋体][font=新宋体][size=4][font=新宋体][font=新宋体][font=新宋体][font=新宋体][font=新宋体]    void SceneGUI(SceneView sceneView)
    {
        if (Event.current.type == EventType.MouseMove)
        {[/font][/font][/font][/font][/font][/size][/font][/font][/color][/size][size=5][color=Black][font=新宋体][font=新宋体][size=4][font=新宋体][font=新宋体][font=新宋体][font=新宋体][font=新宋体]Event.current.Use();
[/font][/font][/font][/font][/font][/size][/font][/font][/color][/size][size=5][color=Black][font=新宋体][font=新宋体][size=4][font=新宋体][font=新宋体][font=新宋体][font=新宋体][font=新宋体]    }


这个委托大概是与场景有关的,与Editor中的OnSceneGUI()一样,将SceneGUI(SceneView sceneView)加入委托后便可以有OnSceneGUI()的效果了。Event.current第一篇里说过,表示当前行为,惯例不懂的百度或者F12看看这个type的枚举有哪些东西。Event.current.Use();表示阻断当前行为,用这个方法可以阻断Button上的点击事件或者阻止拖拽等等,更甚至你可以用它实现所有物体都不能拖拽的功能,那以后Hierarchy上的所有物体,包括project里的物体都不能移动位置了。

二级窗口


使用编辑器你还可以制作二级窗口,建议最好设置一个bool类型的变量,当二级窗口弹出时,让一级窗口不绘制。
放在OnGUI()中即可,if(second)GUI.enable = false;
这样就跟网游的界面一样了,打开装备栏什么的东西,框框外面的地方就不可操作了。
[C#] 纯文本查看 复制代码
if (GUILayout.Button("打开二级窗口"))
        {
            second = true;
            BeginWindows();
            secondWindowRect = GUILayout.Window(1, secondWindowRect, SecondWindow, "二级窗口");
            EndWindows();
        }


这个Window方法,照例F12看看发现它需要一个方法做参数。
[C#] 纯文本查看 复制代码
 void SecondWindow(int unusedWindowID)
    {

            GUILayout.Label("Triangles: " + UnityStats.triangles);
            GUILayout.Label("Vertices: " + UnityStats.vertices);

            if (GUILayout.Button("关闭二级窗口"))
                second = false;
            GUI.DragWindow();//画出子窗口
        }

稍后会整理一个项目发上来,另外Handles类我实在是没用到,贴人家的代码上来也没意义,论坛里关于编辑器的文章也是一大堆,但是我觉得程序员就是一个积累的过程,这个系列文章里也归类了几个我没在其他文章里见到的方法,一并写了进去,记住就好,用到的时候最起码能想到这个API在哪里,或者是用简单一句已有代码实现的功能没必要自己去写一堆代码来做。
WY8DTTFLZRR4LWQ}[EVJT48.png



有写错的欢迎补充,本系列随时整理。等我周末把那个插件的一千多行代码全部撸完又可以大更一次。






回复

使用道具 举报

2初来乍到
113/150
排名
16237
昨日变化
857

0

主题

58

帖子

113

积分

Rank: 2Rank: 2

UID
278671
好友
0
蛮牛币
171
威望
0
注册时间
2018-4-24
在线时间
21 小时
最后登录
2018-5-24
发表于 2018-5-5 11:49:57 | 显示全部楼层
梵蒂冈梵蒂冈地方官

回复 支持 反对

使用道具 举报

排名
31724
昨日变化
4484

0

主题

5

帖子

20

积分

Rank: 1

UID
279371
好友
0
蛮牛币
26
威望
0
注册时间
2018-4-30
在线时间
9 小时
最后登录
2018-5-23
发表于 2018-5-6 10:50:46 | 显示全部楼层
感谢分享

回复

使用道具 举报

4四处流浪
458/500
排名
8767
昨日变化
176

0

主题

228

帖子

458

积分

Rank: 4

UID
180321
好友
3
蛮牛币
369
威望
0
注册时间
2016-11-21
在线时间
114 小时
最后登录
2018-5-24
发表于 2018-5-7 08:13:18 | 显示全部楼层

回复

使用道具 举报

6蛮牛粉丝
1412/1500
排名
6261
昨日变化
94

0

主题

1049

帖子

1412

积分

Rank: 6Rank: 6Rank: 6

UID
267381
好友
2
蛮牛币
2296
威望
0
注册时间
2018-2-1
在线时间
175 小时
最后登录
2018-5-25

迈向小康

发表于 2018-5-7 10:21:28 | 显示全部楼层

回帖奖励 +2 蛮牛币

谢谢分享
[发帖际遇]: 墨染青天 发帖时在路边捡到 2 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
2685/5000
排名
2983
昨日变化
27

0

主题

1888

帖子

2685

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
219676
好友
0
蛮牛币
2472
威望
0
注册时间
2017-7-12
在线时间
365 小时
最后登录
2018-5-24

活力之星

发表于 2018-5-7 13:52:48 | 显示全部楼层
谢谢分享

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表