关于Unity —UIWidgets的详细介绍

作者: 我是Doki | 来源:发表于2019-05-16 15:19 被阅读19次

    UIWidgets(我下面简称它UIVGS)是 Unity 的一个跨平台APP解决方案的插件包,它继承了Flutter精神。因为Flutter有自己的渲染引擎,Unity也有,所以Unity中国写了一套底层渲染API,把Flutter的意志移植到了Unity里成了UIVGS里,所以马上Unity将能开发app了。欢迎大家和我一起学习和开发 totototogether!!(unity无敌)
    开源GitHub地址:
    UIWidgets | 官方交流社区 | 官方录播 | Flutter中文文档
    APPConnect | Markdown RendererForUIWidget

    建了一个UIVGS交流群,希望大家一起交流学习!!二维码

    总结官方的直播视频

    A new way to build beautiful UI in Unity

    1.什么是UIVGS?

    .unity的开源的插件包,将来会放到Asset store和unity的包管理器中。
    .是一个UI框架,是开发者根据flutter的源码和结合unity现状演变、pot过来的。
    .可以构建app、游戏UI界面、编辑器插件的UI界面。

    2.上手UIVGS

    a.声明式的UI框架:开发者只需要C#代码里显示的定义好你的UI形状,布局需求,交互逻辑。下图是框架结构(七分精力原生开发,三分给前端)


    框架结构.png

    b.Hello World演示

    public class StartApp : UIWidgetsPanel
    {
        protected override Widget createWidget()
        {
            return new  Column(
                children:new List<Widget>
                {
                    
                    new Container(
                        width:300f,
                        height:300f,
                        decoration:new BoxDecoration(
                            image:new DecorationImage(
                                image:new AssetImage(
                                    "doki-001")))
                        ),
                    new Text("Doki: Hello UIVGS!",
                        style:new TextStyle(color: Color.white,fontSize:32))
                });
        }
    }
    
    Hello World.png

    c.静态UI布局,UI自适应原理(Technical Details on Layout)
    Bottom-up Resizing :置底向上计算每个widget的大小(确保每个父widget包含所有个子widget)
    Top-down Positioning:至上而下计算每个widget的位置(确定每个父widget的位置后再根据此父widget下开发者定义的布局确定每个子widget确定相对位置)
    最后换算出每个widget的绝对位置


    contain.png

    d.动态UI的布局

    public class TestAPP : UIWidgetsPanel
    {
        protected override Widget createWidget()
        {
            return new Counter();
        }
    
        class Counter : StatefulWidget
        {
            public override State createState()
            {
                return new CounterState();//调用一次 绑定Counter 关联CounterState
            }
        }
    
        class CounterState : State<Counter>
        {
            private int countNum = 0;
            //渲染
            public override Widget build(BuildContext context)
            {
                return new GestureDetector(
                    child: new Text("[TestAPP]Onclick:"+countNum, style: new TextStyle(color: Color.white, fontSize: 50)),
                    onTap: () => { 
                        Debug.Log("<TestAPP>onclick debug");
                        this.setState(() =>
                        {
                            this.countNum++;
                        });
                    }
                );
            }
        }
    }
    
    点击更新.gif
    用户输入,交互Technical Details on Input

    UIVGS会采集Unity EventSystem用户输入信息(touch,mouse等),然后置顶向下传递,确定哪个widget被选中,被选中的widget会相关一个Gesture Delector的widget,Gesture Delector会记录所有的用户输入,并处理转化成更高级的用户输入(长按,点击,双击等),然后发送给所有的监听者(onTap,onPress等)


    Input.png

    创建有状态的组件可以遵循以下步骤:
    1.创建一个继承自StatefulWidget的类来表示你要自定义的可变控件
    2.创建一个继承自State的类来处理这个可变控件的状态和显示样式(build方法)。
    3.当用户交互发生,例如onPressed点击事件被触发时,可以调用setState方法告诉组件需要重绘。


    组件树只更新被标记的UIwidget.png
    e.渲染 Technical Details on Rendering技术
    UIVGS会动态找到适合和相对静止不变的widgets子树,并且将他提前渲染到一个离屏的 Render Texture 上,然后缓存下来,在之后的渲染就不用一笔笔的渲染,只需要把这些不变UI的贴到屏幕上。 性能无敌.gif

    3.为什么UIVGS很重要

    a.更适合做很棒的动画效果、颜色域广等的新用户体验的UI。

    b.可以不仅仅局限于游戏UI界面,还可以做app、editor UI。

    c.可以结合Unity,制作3d和增加粒子效果。

    d.开发者只需要做前端,渲染效率交个引擎底层,解放了人力,提升了效率(运行速度快,基本上fps>60)。
    因为传统用UGUI 不能太耗batches数量 资源 刷新率 Drawcall ,团队用用一个shader,需要合各种图,小图大图 合批。现在用UIWidgets动态合批,比如一个血条,他不变就不合,血条变了就合批。ugui 很耗cpu每次delete就需要合批 重画,每次tps很低,一般就建多个canvas,就把一些静态不变的图放在一个canvas,比如头像,icon等,经常放在一个canvas。UIWidgets有个树形结构,可以解决这些事,所以可以把人力解放出来。相比IMGUI,IMGUI比较原始,太底层,开发者不需要太关心表现层,但更多需要去维护底层逻辑。相比UIElement,UIElement开发模式太老,模仿的还是Html(div+css)。

    4.UIVGS编程模式

    刚上手可以能不太适应,因为习惯了C# 的链式开发,但换一种开发习惯也是很新很酷的开发体验。

    a.关于UI as a function of state(实现业务逻辑和界面的真正的分离,方便理解和维护)

    UIWidgets是和现在react和flutter一样是响应式编程,用状态生成UI。需要注意的是StatefulWidget和Building widgets这两个接口。
    StatefulWidget提供两个方法:
    .setState(fn)(触发状态改变的时候就会触发setState这个接口)
    .build(当开发者通过当前的触发状态自己实现和绘制新的UI,其中每次会生成widget tree,尽管每次都会新生成widgets树,但是每次新生成的树框架(framework)都会和当前的树进行比较,然后仅仅去创建、更新、删除那些底层组件。其次widgets都是一些简单的对象,构建这些对象的开销都非常小,尽管每次去setSate都会building新的widgets,但是这种开销都非常小))


    标记状态每帧过后去更新.png

    b.Router和Navigation(路由和导航器)

    这里可以参考flutter的实现原理,flutter Navigation文档,简单的说Router路由就是注册了所有页面,一个Map结构,对应的Key和value(页面),然后用Navigator用来管理堆栈功能(即push和pop)管理显示页面。

    push和pop操作.png

    c.UIVGS和原生交互

    提供一个了一个叫UIWidgetsMessageManager消息中心管理器的脚本(直接利用Unity和原生的交互的消息机制,做了一个直接的封装,用Unity提供的SendMessage方法发送给GameObject UIWidgetsMessageManager,然后按照不同的channel划分转发消息)。


    Unity Keyboard案例.png
    Android原生.png

    d.开发调试工具

    首先在Unity editori的PlayerSettings 里加一条定义打开开发者模式 UIWidgets_DEBUG.png
    Editor分析器.png

    查看每个widge(大小,权重、位置,颜色,字体等)以及对应的Render Tree的信息

    Refersh

    手动刷新

    Inspect Element

    具体点击UI元素的信息

    DebugPaint

    1.PaintSize:蓝色区域是内边距,淡蓝色线条轮廓线条。
    2.PaintBaseLine:文本对齐的基线
    3.PaintPointer:检测UI响应区域大小
    4.PaintLayer:根据Layer划分widgets子树,做渲染缓存。


    2.gif

    5.Roadmap

    1.更高效:用新推出的DOTS技术,C#任务系统、ECS、Burst编译。
    2.增加Cupertino风格
    3.版本迭代更至Flutter1.2
    4.用Tiny开发,更轻量级

    所以flutter同样适用Unity,用C#写就好

    推荐的Flutter资料 | 每周更新Flutter(外网) | flutter
    建了一个UIVGS交流,希望大家一起交流学习!!二维码

    相关文章

      网友评论

        本文标题:关于Unity —UIWidgets的详细介绍

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