NGUI源码阅读笔记

"开发笔记"

Posted by A-SHIN on March 10, 2018

“Yeah It’s on. ”

前言

由于新开项目开发周期短人手少,最近忙于NGUI界面制作及LUA逻辑编写。之前也一直打算系统地看遍NGUI源码,过年刚好有时间看了一部分,在此记录些要点备忘。剩余部分后续阅读更新。

正文

UIRoot:
UI分辨率设置  
activeHeight计算  
transform.localScale = 2/activeHeight  
content height (如1080) fit勾上后,切换到任何分辨率下高恒定为1080,宽为当前分辨率w/h * 1080。如果一个UI及父物体没有anchor那么坐标值在任何分辨率下是不会改变的。  
UICamera(NGUI Event System):
UICameraTool 统计场景中所有的Camera  
[RequireComponent(typeof(Camera))]  
各种Mouse、Touch、Controller的Event处理,所有可用的响应函数在开头的注释里  
gameObject.SendMessage(funcName, ...)	GameObject下的脚本执行响应函数  
UIRect:
Anchor处理  
AnchorPoint.relative	0:left or bottom	0.5:center	1:right or top	0<=custom<=1  
UIWidget:
Base class for all UI components that should be derived from when creating new widget types.  
Depth controls the rendering order -- lowest to highest.  
raycastDepth = panel.depth * 1000 + widget.depth  
public UIGeometry geometry = new UIGeometry();  
mColor、mPivot、mWidth、mHeight、mDepth  
UIDrawCall:
继承自MonoBehaviour  
drawcallTool 统计场景中所有的drawcall
depthStart、depthEnd  
verts、norms、tans、uvs、cols  
mMaterial、mTexture、mShader、mClipCount、mTrans、mMesh、mFilter、mRenderer、mDynamicMat、mIndices、... 、mRenderQueue、mTriangles  
renderQueue(material)、sortingOrder(render)
如果panel选了clip 则CreateMaterial时会自动替换成带clip功能的shader,并在OnWillRenderObject时传参给shader  
用SHOW_HIDDEN_OBJECTS宏编辑器模式里显示UIDrawCall GameObject,此时的material和shader才是最终渲染所用的。  mDynamicMat是实例化后真正用的material
UIGeometry:
All widgets have one.  
the widget's transformed coordinates only change if the widget's transform moves relative to the panel, so that can be cached as well.  
verts、uvs、cols、mRtpVerts、mRtpNormal、mRtpTan  
UIPanel:
UIPanelTool 统计场景中所有的Panel  
widgets、drawCalls、mAlpha、mClipping、mClipRange、mClipSoftness、mClipOffset、mClipTexture.. 、mDepth、mSortingOrder、mRebuild(为true时重构panel中的所有drawcall)、mResized  
FillAllDrawCalls中产生的每个drawCall负责渲染连续depth的widgets,并且各widget的material和mainTexture、shader分别相同  
LateUpdate时更新UI(TransformMatrix、Layers、Widgets、DrawCalls并对所有Panel中的各个DrawCall设置Transform和RenderQueue等)  
移动Panel的Transform时(子物体跟随移动),Clipping自动反向移动,确保裁切区域在屏幕中位置不变。(UIScrollView)  
每个panel渲染顶点数不能大于等于65000个
UIGrid:
UIScrollView:
UIFont:
UIAtlas:
UILabel:
EventDelegate:
Delegate callback that Unity can serialize and set via Inspector.  
可序列化、通过反射调用委托  
mTarget、mMethodName、mParameters  
UICamera事件响应后通过gameObject.SendMessage(funcName, ...)调用相应组件(如:UIButton)中的相应函数(如:OnClick,然后OnClick会调用EventDelegate.Execute(onClick); onClick为之前设置的序列化的List<EventDelegate>)  
UIEventTrigger:
UIEventListener:
Example usage: UIEventListener.Get(gameObject).onClick += MyClickFunction;  
会自动给gameObject添加UIEventListener组件,UICamera事件响应后通过gameObject.SendMessage(funcName, ...)调用UIEventListener中的相应函数(如:OnClick,然后OnClick会调用之前赋值的委托)  
UITweener:
animationCurve、mStarted、mStartTime、mDuration、mAmountPerDelta、mFactor  
DoUpdate中计算出当前mFactor的值,根据选择的Method算出对应的val,再通过animationCurve.Evaluate(val)计算出对应Keyframe的value。最后传递value给子类调用子类重写的抽象函数OnUpdate处理具体逻辑。  
PlayForward、PlayReverse   #####  TweenPosition:  
调用Begin函数可自动查找或者添加运行一个tweenGroup为0的TweenPosition实例。如果UI中挂了TweenPosition组件,也可调用父类的PlayForward、PlayReverse。   #####  UIPlayTween:  
响应trigger对应事件,根据设置处理tweenTarget的播放逻辑。

执行过程:

首先所有panel排序,然后panel中所有的widget排序后,每个pannel中按排序将相邻相同Material、Texture、Shader的widget中的geometry信息通过WriteToBuffers函数写入到生成的同一个drawcall中(如果panel的clip不为none则需要进行材质替换)并计算drawcall的renderqueue。drawcall的transform为panel的世界transform,geometry里的transform是相对panel的。最后U3D引擎渲染的是drawcall gameobject(drawcall的renderqueue赋值给material.U3D按material的renderqueue顺序渲染drawcall中的meshRender).
UISprite sliced triangles 18 when simple triangles 2 具体UI组件在UpdateGeometry时通过OnFill函数生成几何数据(verts、norms、tans、uvs、cols)到widget的geometry内.
更改widget的alpha或者transform或者SetActive ture or false会使他们对应的drawcall重新WriteToBuffers和UpdateGeometry。更改panel的alpha或者SetActive ture也会。不过更改panel的transform或者SetActive false不会。

待解决:

后记

新项目开始了,996了,引擎开发暂时放放。