NFT将成为元宇宙的关键基础设施,元界悔成为NFT最实出的应用,NFT的独特性和可替代性将为现实世界中的人类沉浸在元宇宙中提供可靠的墓础元宇宙是线上线下世界的融合,物理与电子相结合的方式。元宇宙为虚拟世界深入现实世界铺平了道路,无论是从虛拟到现实,还是从现实到虛拟,都致力于为用户提供更真实的体验。
Image怎么绘制的
Unity中渲染的物体都是由网格(Mesh)构成的,而网格的绘制单元是图元(点、线、三角面)
绘制信息都存储在Vertexhelper类中,除了顶点外,还包括法线、UV、颜色、切线。
Rebuild概念
Canvas负责将子节点的UI元素的网格合并,并生成相应的渲染指令再发送到Unity的图形管道的过程。所以Canvas就是渲染UI的组件,当UI发生变化就要执行一次Batch,它是影响性能更大的元凶。注意Canvas的Batch只会影响其子节点,但不会影响其子Canvas。
Rebuild的程序流程NFT链游开发源码模式威:MrsFU123
Image,Text都是继承Graphic,Graphic有ICanvasElement接口,实现rebuild函数
public interface ICanvasElement
{
///<summary>
///Rebuild the element for the given stage.
///</summary>
///<param name="executing">The current CanvasUpdate stage being rebuild.</param>
/////根据CanvasUpdate的不同阶段重建元素
void Rebuild(CanvasUpdate executing);
CanvasUpdateRegistry监听Canvas的willRenderCanvases事件,这个事件会在渲染前进行每帧调用
public class CanvasUpdateRegistry
{
//布局重建队列,当UI元素的布局需要更新时将其加入队列
private readonly IndexedSet<ICanvasElement>m_LayoutRebuildQueue=new IndexedSet<ICanvasElement>();
//图形重建队列,当UI元素的图像需要更新时将其加入队列
private readonly IndexedSet<ICanvasElement>m_GraphicRebuildQueue=new IndexedSet<ICanvasElement>();
protected CanvasUpdateRegistry()
{
//监听了Canvas的willRenderCanvases事件,这个事件会在渲染前进行每帧调用
Canvas.willRenderCanvases+=PerformUpdate;
}
PerformUpdate收集布局重建队列,图形重建队列调用ICanvasElement.Rebuild完成重建
何时加入重建
通过设置“脏数据”实现的,包括布局(Layout)、材质(Material)和顶点(Vertices)三部分,设置布局为脏,将进行布局重建,设置顶点或材质为脏,则进行图形重建。布局重建会将自身加入m_LayoutRebuildQueue中,图形重建则会将自身加入m_GraphicRebuildQueue中,等待被调用。
SetLayoutDirty:加入到布局重建队列
SetVerticesDirty,SetMaterialDirty:材质,顶点变换加入到图形重建队列
布局重建:位置或者大小;
图像重建:顶点变化,材质变化(大小,旋转以及文字变化、图片的修改)
优化
主要目标,把Profile里Canvas.SendWillRenderCanv参数调小。通过限制顶点数量,顶点变化等。
text属性改变(“123”–>“1234”),触发SetLayoutDirty:在做倒计时相关,按照每1s改变,不要实时改变
改文字,图片颜色,触发SetVerticesDirty(顶点改变),所以改图片颜色最好是改材质球颜色
layout组件引起重建问题
text描边,阴影性能问题
一个字符产生4个顶点,
如果再加上Shadow则相当于又把Text复制了一遍产生8个,
Outline则会将Text复制4遍产生20个顶点。
用相应的shader替换
text渐变
Image格式选择
Image:顶点数量取决于Image Type的选择。
①Simple 4个顶点;
②Sliced勾选FillCenter的顶点数是36个,不勾选是32个;
③Tiled取决于Rectranform设置的大小和原图大小,铺开了N张图就是4*N个;
④Filled选择比较多,但最少也有4个。
所以对于Image首选Simple模式其次则是Sliced模式且不勾选FillCenter
动静分离:Canvas.SendWillRenderCanvases()与Canvas.BuildBatch()的计算是以Canvas为根节点进行的,不同Canvas不会影响另外一个Canvas。但是,大量的动静分离反而影响Canvas的合批,所以可以针对性的对战斗UI,主界面做分离
源码中查看影响重建因素
触发SetLayoutDirty
Graphic:
protected override void OnRectTransformDimensionsChange():当UI的RectTransform更改时的回调,只要继承UIBehavior即可获取回调
Image:
protected override void OnCanvasHierarchyChanged():父画布的状态改变
Text:
text属性改变:在做倒计时相关,按照每1s改变,不要实时改变
public bool supportRichText:设置是否开启富文本时,开关规则(只要状态跟上次不同,SetLayoutDirty一下,而不是开启后实时Dirty)
public bool resizeTextForBestFit:设置是否允许文本自动调整大小时,开关规则
public int resizeTextMinSize:允许的最小文本大小
public int resizeTextMaxSize:设置最大文本大小
public TextAnchor alignment:文本相对其RectTransform的定位。
public int fontSize:文本大小
public HorizontalWrapMode horizontalOverflow:水平溢出模式
public VerticalWrapMode verticalOverflow:垂直溢出模式
public float lineSpacing:行间距,指定为字体行高的一个因子。值为1时将生成标准行间距
public FontStyle fontStyle:字体样式
触发SetVerticesDirty:顶点变化
Graphic:
public virtual Color color:颜色,所以改图片颜色最好是改材质球颜色
protected override void OnRectTransformDimensionsChange():当UI的RectTransform更改时的回调,只要继承UIBehavior即可获取回调
Image:
public Type type:Simple,Sliced等
public bool preserveAspect:是否保持高宽比,开关规则
public bool fillCenter
public FillMethod fillMethod:填充模式
public float fillAmount
public bool fillClockwise
public int fillOrigin
public bool useSpriteMesh:图片透明部分裁剪
protected override void OnCanvasHierarchyChanged():父画布改变
RawImage:
public Texture texture
public Rect uvRect
Shadow:
public Color effectColor
public Vector2 effectDistance
public bool useGraphicAlpha
Text:
public virtual string text
public bool supportRichText
public bool resizeTextForBestFit
public int resizeTextMinSize
public int resizeTextMaxSize
public TextAnchor alignment
public bool alignByGeometry:使用区段的字形几何执行水平对齐,而不是字形指标。
这可以导致更好的拟合左和右对齐,但可能会导致不正确的定位当试图覆盖多个字体(如专业轮廓字体)上
public int fontSize
public HorizontalWrapMode horizontalOverflow
public VerticalWrapMode verticalOverflow
public float lineSpacing
public FontStyle fontStyle
触发SetMaterialDirty:材质改变
Graphic:
public virtual Material material
Mask:
public bool showMaskGraphic:
protected override void OnEnable()
protected override void OnDisable()
protected override void OnValidate():编辑器用
MaskableGraphic:
public bool maskable
protected override void OnTransformParentChanged()
protected override void OnCanvasHierarchyChanged()
public virtual void RecalculateMasking():为此元素和所有子元素重新计算遮罩。
触发SetAllDirty,全改变
Image间接继承自Graphic,当它的Sprite发生变化时,会调用SetAllDirty函数
SetAllDirty改变时机
Graphic:
protected override void OnTransformParentChanged()父物体改变
protected override void OnEnable()
protected override void Reset():赋值默认值,只在编辑器下有用,可无视
protected override void OnDidApplyAnimationProperties():动画属性改变
protected override void OnValidate():脚本加载或Inspector中的任何值被修改时会调用,只在编辑器下有用,可无视
Image:
static void RebuildImage(SpriteAtlas spriteAtlas)图集改变
sprite属性改变
overrideSprite临时修改图片
public override void SetNativeSize()设置大小
Text:
public void FontTextureChanged():字体纹理被修改:TTF动态字体,Text每次赋值的时候Unity会生成贴图,以及保存每个字的UV信息,那么显示字体的时候根据UV信息去生成的贴图里取最终渲染在屏幕上。
font属性更改