精华内容
下载资源
问答
  • Unity 编辑器扩展总结 一:编辑器开发入门

    万次阅读 多人点赞 2018-12-02 14:59:20
    引言: 在项目开发中,编辑器扩展为开发者提供了开发自定义工具的功能,让开发者更加便利地使用编辑器开发项目。近期小生一直在学习编辑器扩展的知识,发现网络上关于编辑器知识点的博客较为零散且混乱。所以决定...

    编辑器扩展总结

    工欲善其事必先利其器

    引言: 在项目开发中,编辑器扩展为开发者提供了开发自定义工具的功能,让开发者更加便利地使用编辑器开发项目。如若博客中存在错误,还请不吝赐教。所有参考的博客或者视频来源将在文末展示。
    扩展: 在Unity2019.1版本后,官方推出全新的保留模式UI框架-UIElements,是一款可以轻松扩展unity编辑器的工具,未来版本可能会支持游戏运行模式。
    开发版本: Unity 2018.1.3f1

    相关博客传送门
    一、编辑器开发入门

    二、编辑器的相关特性

    三、自定义Inspector面板

    四、创建编辑器窗体

    五、Gizmos辅助调试工具

    六、扩展Scene视图

    七、数组或list集合的显示方式

    八、EditorPrefs、ScriptableObject、Undo

    九、GUIStyle、GUISkin

    十、AssetPostprocessor资源导入管线

    编辑器开发入门

    编辑器相关文件夹介绍

    1. Editor
    • 该文件夹可以放在项目的任何文件夹下,可以有多个"Editor"文件夹。
    • 编辑器扩展相关的脚本都要放在该文件夹内,该文件夹中的脚本只会对Unity编辑器起作用。
    • 项目打包的时候,不会被打包到项目中。如果编辑器相关脚本不放在该文件夹中,打包项目可能会出错。
    • 如果非要有些编辑器相关脚本不放在该文件夹中,需要在该类的前后加上UNITY_EDITOR的宏定义
    1. Editor Default Resources
    • 该文件夹需要放在Assets根目录下,用来存储编辑器所需要的图片等资源,书写的时候需要注意中间有空格隔开。此文件夹也不会被打包,访问方法为:EditorGUIUtility.Load()
    • 当然,也可以在Editor文件夹内创建一个Resources文件夹,将相关资源放在该文件夹内,通过Resources.Load()获取资源,也是可以的
    1. Gizmos
    • 该文件夹也需要放在Assets根目录下,可以用来存放Gizmos.DrawIcon()的图片资源

    编辑器扩展的命名空间:
    Using UnityEditor

    [MenuItem]

    添加菜单栏按钮

    [MenuItem(“MyTools/test1”,false,priority)]

    • 第一个参数用来表示菜单的路径;
    • 第二个参数用来判断是否是有效函数,是否需要显示;
    • 第三个参数priority是优先级,用来表示菜单按钮的先后顺序,默认值为1000。一般菜单中的分栏,数值相差大于10。
    • 注意需要是静态方法

      例如:[MenuItem(“MyTools/test1”)]
      也可以添加在Unity默认的菜单栏中,例如添加到Window菜单中,[MenuItem(“Window/test2”)],添加到Assets下,[MenuItem(“Assets/Project中的按钮”)]

    实现点击菜单按钮,删除场景或者Project中选中的多个对象

    [MenuItem("MyTool/DeleteAllObj", true)]
    private static bool DeleteValidate()   
    {
        if (Selection.objects.Length > 0)
            return true;
        else
            return false;
    }
    
    [MenuItem("MyTool/DeleteAllObj",false)]
    private static void MyToolDelete()
    {
        //Selection.objects 返回场景或者Project中选择的多个对象
        foreach (Object item in Selection.objects)
        {
            //记录删除操作,允许撤销
            Undo.DestroyObjectImmediate(item);
        }
    } 
    

    DeleteValidate方法是MyToolDelete方法的有效函数,所以第二个参数为true。该有效函数用来判断当前是否选择了对象,如果选择了,返回true,才可以执行MyToolDelete方法。

    添加快捷键

    符号字符
    %Ctr/Command
    #Shift
    &Alt
    LEFT/Right/UP/DOWN方向键
    F1-F2F功能键
    _g字母g

    例如:[MenuItem(“MyTools/test1 %_q”)] 快捷键 Ctrl+Q

    CONTEXT

    给某组件添加右键菜单选项

    [MenuItem(“CONTEXT/组件名/按钮名”)]
    注意CONTEXT大写

    [MenuItem("CONTEXT/Rigidbody/Init")]
    private static void RigidbodyInit() 
    {
        //TODO
    }
    

    MenuCommand

    用于获取当前操作的组件
    如下,给自定义的组件PlayerHealth添加右键Init按钮

    [MenuItem("CONTEXT/PlayerHealth/Init")]
    static void Init(MenuCommand cmd)
    {
        PlayerHealth health = cmd.contex as PlayerHealth;
    }
    

    ContextMenu、ContextMenuItem

    给某组件添加右边小齿轮菜单选项

    [ContextMenu("FunctionName")]
    public void FunctionName()
    {
        //ToDo
    }
    

    给某属性添加右键菜单选项

    [ContextMenuItem("Handle", "HandleHealth")]
    public float health;
    
    private void HandleHealth()
    {
        //ToDo
    }
    

    P.S. 这两个特性是在UnityEngine命名空间下的,而不像其他[MenuItem]、Selection是在UnityEditor下的。

    Selection

    用于获取选择的游戏物体

    • Selection.activeGameObject 返回第一个选择的场景中的对象
    • Selection.gameObjects 返回场景中选择的多个对象,包含预制体等
    • Selection.objects 返回选择的多个对象
    //遍历选择的对象,并立刻销毁
    foreach(object obj in Selection.objects)
    {
        DestroyImmediate(obj);
    }
    

    P.S. Destroy方法会将删除的对象放在缓存中,缓存满了,才完全删除,而在编辑器未运行的时候,是没有这片缓存的,所以需要用DestroyImmediate(),立刻销毁。当然,可以直接使用Undo.DestroyObjectImmediate()来销毁对象并记录销毁操作

    参考资料

    编辑器特殊文件夹及内置资源读取

    Unity编辑器小教程

    MenuItem和ContextMenu的使用方法

    展开全文
  • 前言本系列将会从零开始开发一个轻量级的AB包编辑器工具(也就是打包或者管理AssetBundle的工具),完成以后,他的最终应用界面可能是如下这样的:界面详解: 1、Create:创建一个新的空的AB包; 2、Rename:...

    前言

    本系列将会从零开始开发一个轻量级的AB包编辑器工具(也就是打包或者管理AssetBundle的工具),完成以后,他的最终应用界面可能是如下这样的:

    这里写图片描述

    界面详解:
    1、Create:创建一个新的空的AB包;
    2、Rename:重命名当前选中的AB包(必须选中任意一个AB包后方可生效);
    3、Clear:清空当前选中的AB包中的所有资源(必须选中任意一个AB包后方可生效);
    4、Delete:删除当前的AB包,同时会自动执行Clear操作(必须选中任意一个AB包后方可生效);
    5、Add Assets:将14中被勾选的资源添加到当前选中的AB包(必须选中任意一个AB包后方可生效);
    6、Hide Invalid:是否隐藏无效的资源(无法打进AB包中的资源,比如.cs .js等);
    7、Hide Bundled:是否隐藏已经打包的资源;
    8、Open:打开右侧的Build Path对应的路径,用于在打包完成后,打开路径取出打好的AB包;
    9、Browse:浏览并选择新的打包路径;
    10、打包对应平台选择;
    11、Build:开始打包;
    12、当前工程的所有AB包预览,白色为空AB包,蓝色为非空AB包;
    13、当前选中的AB包中的所有资源预览(必须选中任意一个AB包后方可生效);
    14、当前工程的Asset路径下的资源结构图预览,无效资源和已打包资源显示为灰色,无法被再次选中并打入新的AB包,已打包资源的后面会显示该资源对应的目标AB包;

    创建编辑器窗口

    首先,我们新建一个类AssetBundleEditor,继承至EditorWindow,那么他将表现为一个编辑器窗口的特征,为其添加一个静态的以便于在外界打开他的方法,并为这个方法添加快捷键触发的功能,%#O 也就对应了快捷键 Ctrl + Shift + O。

        public class AssetBundleEditor : EditorWindow
        {
            [MenuItem("Window/AssetBundle Editor %#O")]
            private static void OpenAssetBundleWindow()
            {
                AssetBundleEditor ABEditor = GetWindow<AssetBundleEditor>("AssetBundles");
                ABEditor.Show();
            }
        }

    这里写图片描述

    编辑器窗口布局

    回顾一下我们窗口的布局,先不用考虑其他那些杂七杂八的按钮。

    这里写图片描述

    1、横向标题栏,当然这里有两层标题按钮,我们可以看到4区域比2区域上面多了一层,为什么呢,因为上面放不下这么多按钮,所以向下多开辟了一层;
    2、一个方形区域,用来显示AB包列表;
    3、一个方形区域,用来显示某一AB包中的资源列表;
    4、一个方形区域,用来显示整个项目中的资源列表;

    首先,我们的布局需求是这样的:
    1、标题栏1区域总是在最上方,这个毋容置疑;
    2、然后区域2和区域3我们将宽度固定,让他们两个平分这个窗口的高度,为什么这样做呢,因为我不想窗口变小的时候会影响这两个区域的宽度,因为那样会妨碍我看某一个东西的名字,毕竟它的名字可能是足够长的,而区域的高度的话,只要添加一个滚动区域,就不怕被拉伸了;
    3、区域4的话,我们让他以左上角为锚点固定,窗口拉伸时,左上角保持不动,因为为了配合区域2和区域3,然后为其添加一个滚动区域就不怕其中的资源过多而导致拥挤了。

    那么,想法已经有了,我们开始干吧。

    编辑器窗口区域划分

    我们已经将窗口划分为了四大模块:标题区域,AB包列表区域,当前AB包资源列表区域,所有资源列表区域。

    代码的话,塞到OnGUI中依次绘制就OK了。

            private void OnGUI()
            {
                TitleGUI();
                AssetBundlesGUI();
                CurrentAssetBundlesGUI();
                AssetsGUI();
            }

    完事了!今天的教程结束!

    ……

    好吧,放下菜刀,我觉得我还能再写点。

    标题区域

    我们先看一下标题区域,将所有的按钮或是其他东西写出来,我们再进行探讨:

            //标记,用于标记当前选中的AB包索引
            private int _currentAB = -1;
            //一种系统样式,使用它就可以使按钮展示为矩形黑框样式
            private GUIStyle _preButton = new GUIStyle("PreButton");
            //一种系统样式,使用它就可以使下拉框展示为矩形黑框样式
            private GUIStyle _preDropDown = new GUIStyle("PreDropDown");
            //是否隐藏无效资源
            private bool _hideInvalidAsset = false;
            //是否隐藏已绑定资源
            private bool _hideBundleAsset = false;
            //打包路径
            private string _buildPath = "";
            //打包平台
            private BuildTarget _buildTarget = BuildTarget.StandaloneWindows;
    
            private void TitleGUI()
            {
                if (GUI.Button(new Rect(5, 5, 60, 15), "Create", _preButton))
                {
                }
                //当前未选中任一AB包的话,禁用之后的所有UI控件
                GUI.enabled = _currentAB == -1 ? false : true;
                if (GUI.Button(new Rect(65, 5, 60, 15), "Rename", _preButton))
                {
                }
                if (GUI.Button(new Rect(125, 5, 60, 15), "Clear", _preButton))
                {
                }
                if (GUI.Button(new Rect(185, 5, 60, 15), "Delete", _preButton))
                {
                }
                if (GUI.Button(new Rect(250, 5, 100, 15), "Add Assets", _preButton))
                {
                }
                //取消UI控件的禁用
                GUI.enabled = true;
    
                _hideInvalidAsset = GUI.Toggle(new Rect(360, 5, 100, 15), _hideInvalidAsset, "Hide Invalid");
                _hideBundleAsset = GUI.Toggle(new Rect(460, 5, 100, 15), _hideBundleAsset, "Hide Bundled");
    
                if (GUI.Button(new Rect(250, 25, 60, 15), "Open", _preButton))
                {
                }
                if (GUI.Button(new Rect(310, 25, 60, 15), "Browse", _preButton))
                {
                }
    
                GUI.Label(new Rect(370, 25, 70, 15), "Build Path:");
                _buildPath = GUI.TextField(new Rect(440, 25, 300, 15), _buildPath);
    
                BuildTarget buildTarget = (BuildTarget)EditorGUI.EnumPopup(new Rect((int)position.width - 205, 5, 150, 15), _buildTarget, _preDropDown);
    
                if (GUI.Button(new Rect((int)position.width - 55, 5, 50, 15), "Build", _preButton))
                {
                }
            }

    这里写图片描述

    我们可以将所有按钮或其他的东西都以绝对位置挨着摆放就可以了,Rename按钮、Clear按钮、Delete按钮、Add Assets按钮等都是针对某一AB包进行操作的,如果当前没有选中AB包的话,这里肯定就要禁用他们的功能,将GUI.enabled = false就是禁用之后的一切控件,遇到GUI.enabled = true的话解除禁用,按钮的摆放的话,这里就没什么难度了,自己拷贝源码编译了看看效果就差不多明白了。

    AB包列表区域

            //区域视图的范围
            private Rect _ABViewRect;
            //区域视图滚动的范围
            private Rect _ABScrollRect;
            //区域视图滚动的位置
            private Vector2 _ABScroll;
            //区域高度标记,这里不用管它,是后续用来控制视图滚动量的
            private int _ABViewHeight = 0;
            //一种系统样式,使用他可以使控件周围表现为一个BOX的模样
            private GUIStyle _box = new GUIStyle("Box");
    
            private void AssetBundlesGUI()
            {
                //区域的视图范围:左上角位置固定,宽度固定(240),高度为窗口高度的一半再减去标题栏高度(20),标题栏高度为什么是20?看一下标题栏的控件高度就行了呗,多余的是空隙之类的
                _ABViewRect = new Rect(5, 25, 240, (int)position.height / 2 - 20);
                //滚动的区域是根据当前显示的控件数量来确定的,如果显示的控件(AB包)太少,则滚动区域小于视图范围,则不生效,_ABViewHeight会根据AB包数量累加
                _ABScrollRect = new Rect(5, 25, 240, _ABViewHeight);
    
    
                _ABScroll = GUI.BeginScrollView(_ABViewRect, _ABScroll, _ABScrollRect);
                GUI.BeginGroup(_ABScrollRect, _box);
    
                //Begin和End中间就是我们要显示的控件列表,当然,如果AB包数量太少,我们的滚动区域还是不能小于视图区域
                if (_ABViewHeight < _ABViewRect.height)
                {
                    _ABViewHeight = (int)_ABViewRect.height;
                }
    
                GUI.EndGroup();
                GUI.EndScrollView();
            }

    这里写图片描述

    这里要怎么解释这段代码?呃我想我最多也只能解释成注释中那样的效果,最难理解的可能就是GUI.BeginScrollView方法中的那三个参数,第一个跟第三个容易搞混,一个表示显示的区域,一个表示可滚动的最大区域,没什么其他好解释的了,最好自己拷贝代码编译了看看效果就熟悉了。

    当前AB包资源列表区域

            //区域视图的范围
            private Rect _currentABViewRect;
            //区域视图滚动的范围
            private Rect _currentABScrollRect;
            //区域视图滚动的位置
            private Vector2 _currentABScroll;
            //区域高度标记,这里不用管它,是后续用来控制视图滚动量的
            private int _currentABViewHeight = 0;
    
            private void CurrentAssetBundlesGUI()
            {
            //区域的视图范围:左上角位置固定在上一个区域的底部,宽度固定(240),高度为窗口高度的一半再减去空隙(15),上下都有空隙
                _currentABViewRect = new Rect(5, (int)position.height / 2 + 10, 240, (int)position.height / 2 - 15);
                _currentABScrollRect = new Rect(5, (int)position.height / 2 + 10, 240, _currentABViewHeight);
    
    
                _currentABScroll = GUI.BeginScrollView(_currentABViewRect, _currentABScroll, _currentABScrollRect);
                GUI.BeginGroup(_currentABScrollRect, _box);
    
                if (_currentABViewHeight < _currentABViewRect.height)
                {
                    _currentABViewHeight = (int)_currentABViewRect.height;
                }
    
                GUI.EndGroup();
                GUI.EndScrollView();
            }

    这里写图片描述

    左边的两个区域就排好了,至于为什么上面的代码会是这样的效果,这就是Rect布局的效果,没看明白的话可以改变其中一些数据看一下窗口变化,只要Rect运用得当,还是可以做出一些不亚于GUILayout才能有的布局效果的。

    所有资源列表区域

    最后一个布局区域,也很简单,原理几乎同上。

            //区域视图的范围
            private Rect _assetViewRect;
            //区域视图滚动的范围
            private Rect _assetScrollRect;
            //区域视图滚动的位置
            private Vector2 _assetScroll;
            //区域高度标记,这里不用管它,是后续用来控制视图滚动量的
            private int _assetViewHeight = 0;
    
            private void AssetsGUI()
            {
            //区域的视图范围:左上角位置固定,宽度为窗口宽度减去左边的区域宽度以及一些空隙(255),高度为窗口高度减去上方两层标题栏以及一些空隙(50)
                _assetViewRect = new Rect(250, 45, (int)position.width - 255, (int)position.height - 50);
                _assetScrollRect = new Rect(250, 45, (int)position.width - 255, _assetViewHeight);
    
    
                _assetScroll = GUI.BeginScrollView(_assetViewRect, _assetScroll, _assetScrollRect);
                GUI.BeginGroup(_assetScrollRect, _box);
    
                if (_assetViewHeight < _assetViewRect.height)
                {
                    _assetViewHeight = (int)_assetViewRect.height;
                }
    
                GUI.EndGroup();
                GUI.EndScrollView();
            }

    这里写图片描述

    OK,我们完成了整个界面的框架(空壳)设计,当然这是一个简单到爆而且极度不美观的界面,不过这无法妨碍我们之后在其中添加一些我们所关心的控件。

    展开全文
  • Unity编辑器开发(一):准备工作

    万次阅读 多人点赞 2018-02-08 19:11:13
    其实,说到Unity的编辑器开发,最大的用途就是用来开发一些实用工具或者说是插件,所涉及到的基本知识也就是Unity最早期的GUI系统的运用,只要对GUI系统运用得炉火纯青,那将自己的工具或者插件做到一流水准也不是不...

    前言

    其实,说到Unity的编辑器开发,最大的用途就是用来开发一些实用工具或者说是插件,所涉及到的基本知识也就是Unity最早期的GUI系统的运用,只要对GUI系统运用得炉火纯青,那将自己的工具或者插件做到一流水准也不是不可以的。

    编辑器的扩展开发,其实最基本的便是掌握对如下三个方法的扩展和使用:
    1、UnityEditor.Editor.OnInspectorGUI()
    2、UnityEditor.Editor.OnSceneGUI()
    3、UnityEditor.EditorWindow.OnGUI()

    OnInspectorGUI

    组件的Inspector窗口GUI显示方法,调用时机:组件挂载的物体被选中,且界面重新绘制时系统自动调用。

    重写自定义组件的Inspector界面

    例:TestEditor类继承至Editor,指向的自定义组件为Test类(由CustomEditor特性指向),则TestEditor重写父类的OnInspectorGUI方法之后,OnInspectorGUI中的内容(主要是GUI控件)将做为Test类在场景挂载后在Inspector窗口的展示界面。

    注意:TestEditor.cs必须放在Editor文件夹内,Test.cs随意。
    这里写图片描述

    代码:

    [CustomEditor(typeof(Test))]
    public class TestEditor : Editor {
        //OnInspectorGUI中的GUI控件将显示在Test类的Inspector窗口
        public override void OnInspectorGUI()
        {
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("This is a test!");
            EditorGUILayout.EndHorizontal();
        }
    }
    

    在场景中选择任意物体挂载Test脚本,选中这个物体,查看Test脚本的Inspector窗口:
    这里写图片描述

    在界面中显示或更新数据

    例:每一个TestEditor类的实例,持有一个Test类的实例(其实就是挂载在场景中的当前选中的物体上的Test组件),在TestEditor类中获取Test类的实例,只需要调用一个从父类继承来的属性,target。

    代码:

    public class Test : MonoBehaviour
    {
        public string Value = "This is a test!";
    }
    
    [CustomEditor(typeof(Test))]
    public class TestEditor : Editor {
    
        private Test _test;
    
        private void OnEnable()
        {
            _test = target as Test;
        }
        public override void OnInspectorGUI()
        {
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label(_test.Value);
            EditorGUILayout.EndHorizontal();
        }
    }
    

    在场景中选择任意物体挂载Test脚本,选中这个物体,查看Test脚本的Inspector窗口:
    这里写图片描述

    OnSceneGUI

    组件的Scene窗口扩展显示方法,调用时机:组件挂载的物体被选中,且界面重新绘制时系统自动调用。

    扩展自定义组件的Scene界面

    OnSceneGUI方法中主要使用Handles系列来绘制可视化调试控件,比如线、盒子、球体、文本等。

    代码:

        public void OnSceneGUI()
        {
            Handles.Label(_test.transform.position, "This is a test!");
        }
    

    在场景中选择任意物体挂载Test脚本,选中这个物体,查看Scene窗口:
    这里写图片描述

    OnGUI

    自定义EditorWindow的GUI显示方法,调用时机:EditorWindow界面重绘时系统自动调用。

    例:新建TestWindow类,继承至EditorWindow,在TestWindow类中实现OnGUI方法。

    注意:TestWindow.cs必须放在Editor文件夹内。
    这里写图片描述

    代码:

    public class TestWindow : EditorWindow {
    
        //注册方法到标题栏:Window/TestWindow
        [MenuItem("Window/TestWindow")]
        private static void Open()
        {
            TestWindow test = GetWindow<TestWindow>();
            test.Show();
        }
    
        private void OnGUI()
        {
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("This is a test window!");
            EditorGUILayout.EndHorizontal();
        }
    }
    

    点击标题栏Window/TestWindow选项,打开一个新的自定义窗口:
    这里写图片描述

    这里写图片描述

    接下来,我们所有的扩展开发很可能都只在这三个方法中进行。

    展开全文
  • 用Unity开发的游戏, 需要做个关卡编辑器. 如果只是内部用用, 其实直接扩展Unity就够了; 但问题是需要发布给外部的用户使用, 那么总不能把全套资源和Unity发给他们, 所以就诞生了这么个奇葩需求. 技术挑战 既然...

    需求背景

    用Unity开发的游戏, 需要做个关卡编辑器. 如果只是内部用用, 其实直接扩展Unity就够了; 但问题是需要发布给外部的用户使用, 那么总不能把全套资源和Unity发给他们, 所以就诞生了这么个奇葩需求.

    技术挑战

    • 既然用了Unity引擎, 那么渲染肯定还是用Unity, 怎么在外面套一堆UI面板?
    • UI需要使用传统的方式来开发, 什么Qt/Winforms/WPF/Web等, 用Unity内置的UI也是一个思路
    • 游戏内的逻辑基本都在mono虚拟机上跑, 外面再搞一套UI逻辑的话, 怎么做到公共代码的复用?
    • Unity在不改源码的情况下没法直接跟外部的UI框架逻辑互调, 所以需要进程间通信
    • 在跨进程的情况下, 怎么做到比较方便的方法调用和属性编辑?

    GUI框架技术

    Unity渲染窗口

    问题就是怎么把Unity嵌入到现有的一些GUI窗口中? 搜索一下已经有人问过了:
    https://answers.unity.com/questions/871077/how-to-display-unity-scene-in-a-qt-window.html
    https://stackoverflow.com/questions/44059182/embed-unity3d-app-inside-wpf-application
    都是利用了Unity的一个命令行参数”-parentHWND”, 游戏启动后会自动做为子窗口嵌入到指定的HWND窗口中.
    还有另外一个思路, 就是使用类似ActiveX的Web控件技术, 不过这种对于游戏的改动太大, 使用上也有比较多限制, 所认不推荐.
    Unity安装完后在Editor\Data\Documentation\en\uploads\Examples\EmbeddedWindow.zip下面有一个嵌入Winforms的示例, 算是一个很好的开始:
    这里写图片描述

    GUI

    本来想尝试一下使用Web前端技术做UI的, 比如像https://threejs.org/editor/, https://victhorlopez.github.io/editor/, https://webglstudio.org/demo/, https://www.mixamo.com 等, 看起来挺酷, 但是考虑到Unity在Web端的技术限制和游戏代码的共享, 放弃了这个方案, 留给下次做工具时再尝试吧.
    如果是C++项目, 那我会首选Qt, 之前折腾CLI的interop给自己留了下心理阴影…因为Unity游戏的主力语言还是C#, 所以只要选了Qt, 就绕不过interop, 放弃好了.
    然后是WPF, 之前也折腾过一阵子, 虽然看起来很酷, 但是自己想做出那么酷的效果还是要花比较多的精力, 上手成本也是个问题, 编辑器做到差不多的时候总要有其他人来接手维护, 像我几年没用过WPF都忘了怎么写XAML了-_-, 算了, 还是选个最简单的Winforms吧, 完全不需要什么学习成本.

    Docking

    对于一个面板很多的编辑器来说, Docking应该是必备的一个特性, 要不然就像以前的MFC开发的编辑器一样, 一堆Tabs挤在一起…本来WPF那边的选择有很多, 不过放弃WPF后, Winforms这边, 如果不选择商用控件库, 那么最好用的应该就是DockPanel Suite. 不过在找Theme Style相关的方案过程中, 意外发现了个DarkUI, 跟Unity整合一下看起来还不错:
    这里写图片描述
    不过里面的控件类型不是很全, 考虑到后期造轮子的成本, 选择暂时放弃, 后续有需要可以参考它的控件风格实现. 如果只是Docking的话, 还是DockPanel Suite做得更好. 但是对于编辑器来说, 黑色风格的显然看起来更加高大上.

    Property Editor

    每次做编辑器都躲不开做个通用属性编辑, 选择C#也是有这方面的考虑. 想当年用MFC开发编辑器时, 每个参数都加一个控件, 那体验…维护起来简直想死. 后来我就入了.Net Interop的坑, 想来可能仅仅是因为这个PropertyGrid:
    这里写图片描述
    再后来放弃了C#, 参考HeliumProject基于C++搞了一整套反射序列化, 用Qt实现了一个通用的属性编辑器.
    这里写图片描述
    不过这东西想要做到体验好, 还是需要非常多的定制化控件, 而3D游戏的基础数据类型每个引擎的定义都不一样, 很难做成通用的. 有空的还是想基于C++搞一套反射+序列化+GC+属性编辑+脚本绑定的通用库, 这样再做其它的编辑器就很轻松了.
    跑题了, 回到C#这边. WPF能找到的比较不错的属性编辑器大多是商用的:
    这里写图片描述
    开源的做得还不错的有Property Tools, 以前我干过把它嵌入到MFC编辑器里的奇葩事, 这次差一点又想把它嵌入Winforms里用. 之所以没选择它, 那是因为我发现了个更好的: AdamsLair.WinForms, 开源2D引擎Duality背后的一个控件库.
    这里写图片描述
    它自带的编辑器Dualitor已经证明了这个属性编辑控件的强大, 针对不同的游戏引擎的数据类型也已经有一些扩展控件参考:
    这里写图片描述这里写图片描述这里写图片描述

    小结

    Dualitor中除了属性编辑, 其它特性的实现也非常不错, 值得拿来学习. 因为2D引擎没有3D引擎那么复杂, 所以其中的代码逻辑还是比较清晰条理的, 本身的设计理念又跟Unity非常类似, 所以照着它的结构跟Unity又杂交了一下:
    这里写图片描述
    看起来还不错, 结合Winforms的所见即所得的GUI编辑器, 再加上这次也不用折腾Interop了, 算是一个挺不错的开始.


    腾讯云自媒体分享计划: https://cloud.tencent.com/developer/support-plan?invite_code=1lss32a6pqj5w

    展开全文
  • 微信公众平台开发之微信编辑器开发是子恒老师《微信公众平台开发》视频教程的第11部。详细讲解了用php进行微信编辑器的开发。内容包含微信公众号编辑器开发思路,编辑器前端页面,功能实现,添加新样式等等。欢迎...
  • Unity编辑器开发(二):四大GUI系统

    千次阅读 多人点赞 2018-02-08 20:51:32
    首先,对于编辑器中的GUI系统,我们可以分为四大类: 1、UnityEngine.GUI 2、UnityEngine.GUILayout 3、UnityEditor.EditorGUI 4、UnityEditor.EditorGUILayout GUI系统 这是运用最广泛的GUI系统...
  • 在去年10月份左右,接到了需求:开发一个H5移动端页面编辑器的任务,目的主要是解放公司内在制作这类网页的所投入的人力以及解决使用外部H5编辑器所涉及到的版权问题。 因此,一款能够与市面上已经成型的H5编辑器...
  • 在上一篇《原理结构篇》中,主要针对移动端网页进行了分类描述,并介绍了H5编辑器的需求、原理以及框架结构,本文将延续开发实战这一主题,针对策略和开发技巧做进一步的介绍。 二、策略篇 2.1 适应策略 ...
  • Web前端开发工具(编辑器)汇总

    千次阅读 2020-08-10 10:20:51
    1、文本编辑器应用:操作系统自带编辑器(如Windows系统的记事本、Unix及类Unix系统文本编辑器Vim)、EditPlus、Notepad++等; 记事本 windows自带的记事本,可直接运行,无需卸载与重装。notepad.exe事实上就是一个...
  • Cocos creator 编辑器开发环境配置

    万次阅读 2018-01-25 20:19:28
    安装配置原生开发环境 除了内置的 Web 版游戏发布功能外,Cocos Creator 使用基于 cocos2d-x 引擎的 JSB 技术实现跨平台发布原生应用。在使用 Cocos Creator 打包发布到原生平台之前,我们需要先配置好...
  • 今天博主想和大家分享的是Unity3D场景编辑器的扩展开发,相关的话题我们在Unity3D游戏开发编辑器扩展程序开发实例这篇文章中我们已经有所涉及,今天博主想特别针对场景编辑器的扩展开发来进行下深入研究。...
  • 在阅读本教程之前,你需要对Unity的操作流程有一些基础的认识,并且最好了解内置...如何让编辑器运行你的代码Unity3D可以通过事件触发来执行你的编辑器代码,但是我们需要一些编译器参数来告知编译器何时需要触发该
  • vscode编辑器 开发小程序插件

    千次阅读 2018-07-26 09:33:52
    用 vsCode 开发微信小程序可以配置以下插件,开发起来更方便: 1. vscode weapp api 2. vscode wxml 3. vscode-wechat 4. Easy WXLESS
  • 首先,我这个文章不会写非常详细的代码,但是我会把我目前博客开发的富文本编辑遇到的问题罗列出来。然后一点点的说明如何解决。说实在目前遇到的问题,已经想让我放弃自己开发富文本了,真的是非诚勿扰。这个坑没...
  • 编辑器导出的数据为2进制数据,并经过gzip压缩,体积非常小。 使用方法: 1.首先制作预制体 将游戏中的道具等做成预制体,将MSBaseObject拖到预制体上并保存。 关卡编辑器只能识别挂有MSBaseObject脚本的...
  • Sublime开发编辑器

    千人学习 2018-03-09 11:35:45
    Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。...Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。
  • 在线电子病历编辑器功能预览,支持Firefox/Chrome/Opera/UC/IE/Safari.演示地址 http://www.dcwriter.cn:9090/ 在WINFORM.NET中的效果 在各个浏览器中的展示效果   ...
  • 微信开发之使用第三方图文编辑器

    千次阅读 2015-07-18 19:44:01
    一、比较好用的第三方图文编辑器 i排版 秀米排版 二、主题色的确定 公众号图标或者logo的颜色; 推文的色彩(喜庆的或忧伤的…); 切记颜色太杂。 三、结构的确定 标题: 多个标题最好进行编号; 同一个等级的标题...
  • 10款开发常用的代码编辑器

    万次阅读 2016-10-28 10:49:21
    这篇文章会介绍10个优秀且免费的编辑器,它们都是非常方便易用的环境,你可以用它们来编写代码,查看源文件和文档等,简化你的工作。  Notepad++    Notepad++是一款免费但优秀的代码编辑器,运行在...
  • TWaver可视化编辑器(二)3D编辑器

    千次阅读 2017-08-11 16:17:38
    作为一款高效、轻量、自带编辑功能小组件,TWaver Java在电信网管界一炮而红,在各大运营商的OSS,BSS,NMS系统中随处可见。
  • python编辑器,新手小白入门指南

    千次阅读 2019-08-21 16:59:55
    刚开始接触编程,有一个好的编辑器上手,那学习起来肯定是事半功倍的!本篇就给大家介绍适合零基础小白学习Python的四种编辑器,希望大家受用! 1.Sublime Text: 这是一个轻量级的代码编辑器,跨平台,支持几十种...
  • 雨松MOMO带你走进游戏开发的世界之地图编辑器的使用以及绘制地图源码。
  • //【AssetBundleEditor.cs】 private AssetBundleInfo _assetBundle; private void TitleGUI() { if (GUI.Button(new Rect(5, 5, 60, 15), "Create", _preButton)) { //新建一个AB包对象,并将之加入到AB包...
  • //【AssetInfo.cs】 public class AssetInfo { }

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 577,520
精华内容 231,008
关键字:

编辑器开发