编辑器

作者: golden_age | 来源:发表于2016-09-03 11:45 被阅读0次

    (2014年旧文)
    今年工作的很多内容是编辑器,给策划做的编辑器,给美术做的编辑器,各种小工具等,
    我想,工具和编辑器在今天更成为游戏开发中重要的手段,

    1. 更精确,更好的表现力制作;
    2. 把人从枯燥重复的工作中解脱出来,进入到一个高效愉悦的工作流;
      unity/UE这些游戏引擎,它们既不是渲染最好的,也不是效率最好的,但他们真正吸引之处是在于它们编辑器的强大,未来,也许是一个面向工具的游戏制作方式呢.


      图1. 动画编辑器
      片头动画,过场动画,算是3D游戏的标配吧, 谈下编辑器的UI方式,
      这里使用了unity gui扩展,也就是类似于maya script那样通过脚本的方式,在主UI上写扩展的菜单,扩展windows,但unity的扩展方式还是另人惊奇的,它实现了一种 Immediate-Mode GUI, 比如说

    if(guilayout.button("点击1")   
        Debug.log("完成点击1");
    if(guilayout.button("点击2")   
        Debug.log("完成点击2");
    

    很简单,这里是两个按扭的显示,和两个按钮的点击响应!对于没有其它GUI经验的人似乎很自然,但细思极恐......它如何做到无阻塞地做到GUI显示和响应的呢, google之: Immediate-Mode GUI......

    另一个例子,GUILayout.BeginVertical()//垂直UI排版,if(guilayout.button("点击1")....if(guilayout.button("点击n")....GUILayout.EndVertical()这似乎破坏了多年GUI的实践的共识——布局与逻辑分离,不过使用起来却很舒服,看起来“不合规矩”的设计,在合适的场景都是有用的。unity扩展是极好的,但也体验了不少坑,

    1. 一些细节,比如说untiy的输入框(中文输入)是有问题的,
    2. 一些限制,GUI样式缺乏,无法多窗口控制,你最好只做在一个窗口上,
    3. 一些无力,这种immd mode的GUI,把UI和逻辑混大一块,渲染和用户输入同一循环,你会发觉越写越吃力,越写绘制性能越坏...
    4. 一些考虑,扩展脚本方式,编辑器代码暴露在外;在技能编辑器里,我考虑了另一种方式,以独立工具形式提供的编辑器,可是,unity是一个封闭的开发环境,这怎么做呢?


      图2. 技能编辑器,WPF + unity exe,..这里可谈的两点,

    一. WPF
    WPF教会了我很好的GUI,和编辑器的设计方式,这超越了我之前对GUI的认识,上升到理论高度就是,

    • 高度交互的程序,其实是个”约束传播模型“,就是一个值(输入,对象) 的变化,会传播到系统的各处,那么其实需要做好的,就是建立这种约束模型,在WPF层面上,对应的就是”依赖属性”之类的概念;
    • 模型映射,对象模型如何对应表现层?从表现到模型 需要建立一种 “同态”的映射,你一定会想到MVC之类的模式,WPF推荐的是一种MVVM方案,我理解的就是,重视view-mode层,以这个接口层去控制 view 和 mode两个模型,它既不会像view那样有着表现的具体实现,又不会像model那样是块无传播约束的数据,它建立的是约束模型,驱动model, 会双向映射到view, ——不知你懂我意思了没,一切以官方mvvm说明。

    二. 进程交互刚开始,我也在想,我如何处理如此多的交互类型呢,我又如何去做到异步交互呢,但当我看到WCF(你没听过的话,想想同样是MS技术的WPF)的方案时,问题就不大了,WCF提供了 c#的RPC方案,因此,并发程序可以像单个进程那样实现了,
    定义一个 unity服务,

    interface IUnity
    {
    }
    

    和一个 editor服务,

    interface IEditor
    {
    }
    

    坏的事情是,当我们工程升级到 unity 4.6时,mono提供的WCF终于不能用了(且不说它之前总是死锁,有些模式未提供什么的),我只好实现自己的RPC方案,
    最后,我发觉这异常好用,

    //editor 进程
    IUnity unityProxy = new Service.Client<IUnity>("127.0.0.1", 10086).getProxy();
    unityProxy.loadScene(...)......
    //unity 进程
    var unityServer  = new Service.Server<IUnity>(10086, new UnityImpl() );
    unityServer.run()
    

    我设计了 CPS(continue pass style) 方式的接口,处理异步.

    //cont(true/false) 返回是否成功
    void loadScene(string fpath, System.Action<object> cont);
    

    如此,我希望能够在交互程序设计这块,探索出更好的经验
    (2014年旧文)

    相关文章

      网友评论

          本文标题:编辑器

          本文链接:https://www.haomeiwen.com/subject/aavkettx.html