自读Unity3d UGUI源码(一)Graphic

前言

尽量用最简单易懂的文字说明。因为自己也是个菜鸡,所以会用菜鸡也听得懂的话来说。
思路是先看父类,然后一层一层下去,中间遇到没见过的类就点进去看一下。

源码下载地址

https://bitbucket.org/Unity-Technologies/ui/downloads/?tab=downloads

UIBehaviour

一切UI组件的父类。叫爸爸。
是一个抽象类,定义了一堆虚方法,以及实现了唯一的一个实方法IsDestroyed()
**除了**unity本身的几个生命周期方法之外,还定义了几个值得注意的虚方法:
- OnRectTransformDimensionsChange()
- OnBeforeTransformParentChanged()
- OnTransformParentChanged()
- OnDidApplyAnimationProperties()
- OnCanvasGroupChanged()
* OnCanvasHierachyChanged()

Graphic

可视元件之祖。
要求一定要有CanvasRenderer和RectTransform这两个组件。

话说起来CanvasRenderer是啥?
这个东西属于UnityEngine命名空间的,提供了一些可视的方法比如:
- Get/SetMaterial
- Get/SetAlpha
- Get/SetColor
- SetMesh
- SetTexture

Fields

  • 有一个public static的默认材质,从canvas里面取,就是空材质的意思了。
  • 颜色,默认是白色
  • 是否为rayCastTarget,布尔值
  • 当然,要有上述两个必须的部件为私有域,还要持有一个Canvas(不知为何
  • 两个dirty标志位,一个是verts,一个是material;三个dirtyCallback:layout, verts, material。
  • 一个静态的Mesh(不知何用

Methods

  • 构造方法是protected的,不能外部调用。
    新建并初始化了一个ColorTweenRunner,现在还不知道干啥用的。
  • 几个SetDirty方法
    做各自的逻辑,并执行对应的callback(如果有的话)
    • SetLayoutDirty
      设置标志位并执行:
      csharp
      LayoutRebuilder.MarkLayoutForRebuild(rectTransform);

      这里注意LayoutRebuilder。把自己标志位需要布局重绘。
    • SetVerticesDirty
      设置标志位并执行:
      csharp
      CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);

      同样这里注意CanvasUpdateRegistry,据我看cocos2dx代码的经验,这里应该是说注册了下一帧update的时候,来更新顶点。
      进去一看,就是把这个ICanvasElement给放到队列里面去,这个队列名字叫m_GraphicRebuildQueue
    • SetMaterialDirty
      csharp
      CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this);

      应该是重绘的意思,设置了material之后就会执行这个方法。
  • OnBeforeTransformParentChanged
    从canvas上解除自己的监听,然后要求layoutRebuild。
  • OnTransformParentChanged
    CacheCanvas,重新绑定到canvas(before的时候取消注册了)
    GraphicRegistry.RegisterGraphicForCanvas(canvas, this);
    然后设置所有dirty。

    CacheCanvas()
    从gameObject取出Canvas列表,然后把第一个设置为m_Canvas
    所以这里又有一个问题,为啥graphic身上会有一个canvas??


分割线~~~
既然这么多次提到了GraphicRegistry. RegisterGraphicForCanvas(Canvas, Graphic)
看了一下,做了啥呢。从instance.m_Graphics里面以canvas为key取出一个IndexSet,然后把graphic添加进去。如果木有这个队列,就创建这个队列然后塞进去。
于是 下一个问题就是:这个队列干嘛用的呢?
首先这个字典是private readonly的,用处有三个方法,一个注册,一个注销,以及一个取出来的方法
GetGraphicsForCanvas(Canvas canvas)(全局搜索发现这个方法被GraphicRaycaster.Raycast()用到啦~非常好)。
所以说这一切都是为了Raycast!!只是为了射线检测而已!! 这样子的话不会很蠢吗!!!!
  • OnEnable
    把canvas缓存起来,然后注册自身到canvas。最后SetAllDirty()。
  • OnDisable
GraphicRegistry.UnregisterGraphicForCanvas(canvas, this);
CanvasUpdateRegistry.UnRegisterCanvasElementForRebuild(this);
- 注销canvas
- 不需要update了
- canvasRenderer.Clear() 啥意思呢? 
> Remove all cached vertices.
- 因为disable了,要消失了,所以叫布局可以重新布局啦~
`LayoutRebuilder.MarkLayoutForRebuild(rectTransform);`

所以要看一下这个LayoutRebuilder究竟怎么实现重绘的,应该最后会execute到具体某个layout上面去。
另外,要明确一下顶点的概念。清除顶点又是啥意思?

  • OnCanvasHierarchyChanged
    把自己从原来的canvas给注销掉,然后注册到新的canvas。

  • Rebuild
    不知道干啥用的

  • UpdateMaterial
    调用canvasRenderer的SetMaterial和SetTexture,说明实际上绘制是在CanvasRenderer。

  • UpdateGeometry
    以及他所调用的DoMeshGeration和DoLegacyMeshGeneration都是改变顶点的,先不看。

  • OnPopulateMesh
    似乎和Mesh有关系,Image里面也会有,这里先不看了。

  • Raycast
    这是重头戏了,关于射线检测啥的,这里先不看。里面会调用ICanvasRaycastFilter接口,看看有没有被射到,有兴趣先看的同学,去看一下Image的实现。

  • CrossFadeColor
    颜色渐变,没兴趣看。

猜你喜欢

转载自blog.csdn.net/hhh132/article/details/80341154