UI常见优化
收集一些常见的UI优化手段和思路。当然,大部分是抄的,希望以后自己有能力总结。
Unity性能优化优化关键先找到性能瓶颈。影响图形性能的关键因素主要有一下几个方面。
GPU填充率和存储器带宽。
CPU经常是渲染物体的数量(也就是常常大家说的Draw Calls)。
系统内存容量也是优化的一个关键指标。
GPU优化GPU优化主要有下面几点:
减少三角形的使用数量(去掉不必要的三角形面)。
尽量避免使用实时光照,能使用Static Lighting就使用烘焙光照,只计算一次。
压缩纹理和多重纹理-mipmap(这样可以提高加载速度和降低内存占用),也极大提高渲染的性能。
LOD(多细节层次),不同距离使用不同精度的模型。
编写高性能着色器,将能能处理的逻辑放在定点着色器里面处理,减少片段着色器的计算量。
CPU优化CPU主要开销在,显卡在渲染一个对象之前,CPU需要计算一些着色器和灯光影响,然后想显卡驱动发送绘制指令,单物体来说,不会太影响性能,累计就会产生性能问题。这里优化点主要从以下几个方面讨论,这里只是说出优化常用的方案,后面如果在下在项目里面遇到更 ...
Unity生命流程
生命流程图
FixedUpdate1、和Update主帧循环不同,Unity的刚体系统通过固定的时间来驱动也就是FixedUpdate。在刚体系统运算开始前,Unity会根据上一次刚体运算完成的时间再加上Fixed Timestep的所设置的值来作为这一次刚体运算时间的限定范围。然后刚体系统会开始计算,直到达到这个时间限制临界点。
2、FixedUpdate与Update的不同在于,Update在每帧被调用,但是调用时间不确定,所以我们要实现一个物体匀速运动是,是无法通过Update准确实现的,但是我们可以在FixedUpdate中实现,因为它在确定的时间间隔中被调用。FixedUpdate有可能在Update之前调用多次。FixedUpdate除了用来处理物理逻辑之外并不适合处理其他模块的逻辑。
3、FixedUpdate的频率可以自己设置,如果频率过高,导致一次Update的时间片内执行了多次FixedUpdate进行物理运算,那对CPU就是一种浪费(因为根本不显示出来);而适当的低频率FixedUpdate,虽然偶尔会造成人物有顿感,但是往往是可以接受的。
4、FixedUpda ...
Unity常见UI基础问题手册
仅作个人笔记用途。
UI顶层显示方法一.做一个新的UI摄像机① Canvas的Render Mode设置为Screen Space - Camera
② 新建摄像机(后面称之为UI摄像机),放到原先摄像机的下面
③ 拖拽UI摄像机到Canvas的Render Camera
④ UI摄像机的 Clear Flags 设置为 Depth only,用来去掉背景;Culling Mask设置为 UI。
⑤ 确保 UI摄像机的Depth > 其他摄像机的Depth (值小的会先渲染,所以值大的会在前面)
参考超级细致的调试教学视频
UGUI学习 - Base篇
序言源码地址
学习博客
GF源码看了,UGUI自适应用了,自定义编辑器写了,但是对于UGUI却一直是纯黑盒使用。想体系化学习一遍UGUI。
学习目的:按照博客阅读源码,理解后整理成自己的笔记,方便回忆。
目录总览图好图,转自大佬博客!
UIBehaviour
namespace UnityEngine.EventSystems :
public abstract class UIBehaviour : MonoBehaviour
是一个抽象类,里面提供了一系列虚方法:
生命周期(Awake,OnEnable,Start,OnDisable,OnDestroy)
UnityEditor 辅助方法
UGUI 通用方法(IsActive,OnValidate,OnRectTransformDimensionsChange等锚点相关)
和一个非虚方法 IsDestroyed:
1234public bool IsDestroyed(){ return this == null;}
UGUI学习 - 事件系统、射线检测
图片转自大佬博客,非常好的入门:https://zhuanlan.zhihu.com/p/437704772。
事件系统总的来说事件系统分为3个大组件:
EventSystem组件 负责管理 所有的输入检测模块(InputModule)并在Update中每帧调用Module的执行(Process)。
InputModule组件 负责输入(点击、拖拽、选中等),调用Raycaster获得返回值PointerEventData,最后通过ExecuteEvents触发事件(IPointerClickHandler 等)。
Raycaster组件 负责确定目标对象,返回结果PointerEventData给InputModule组件。
相互之间的协作⭐EventSystem会在Update中调用输入模块的Process方法来处理输入消息;
PointerInputModule的Process方法会调用EventSystem中的RaycastAll方法进行射线检测;
RaycastAll又会调用所有BastRaycaster的Raycast方法执行具体的射线检测操作,用以获取屏 ...
C#精要 - 同步异步、多线程篇
零.为什么我会理解错在看完clr之前,我曾对异步同步探究看了十几篇文章,但很可惜,没有完全理解,只知道了一大堆概念:IRP、异步要借用多线程…
在看完之后,我理解并甚至尝试实现一个简单的异步的时候才明白,之前无法理解是因为我不懂:
异步编程 和 异步函数 是不同的东西。也就是说,异步函数async/await 只是异步编程的一种罢了,你大可以利用ContinueWith或ThreadPool等来实现异步。
很多博客混淆了这两个概念,我不知道他们是否真正理解了,但是这会导致我这种代码先行基础后补的菜b无法理解。
所以这篇文章的理解是片面的,等有空了我再整理一下。
一.同步与异步 项目中每天都在接触,但是对这俩概念比较模糊。看《CLR via C#》刚好提到了,就去网上找到几篇好文,理解写篇自己的笔记。首先得说明的是,这一节讨论的只是概念,都是单纯的、不考虑多线程处理的同步与异步区别。
IO 概念区分
同步(Synchronous)
异步( Asynchronous)
阻塞( Blocking )
非阻塞( Nonblocking)
那首先,要弄清楚同步异步、阻塞非阻塞之间的关 ...
C#精要 - Mono篇
IL是什么?IL的全称是 Intermediate Language,是一种中间语言。它是一种属于通用语言架构和.NET框架的低阶(lowest-level)的人类可读的编程语言。目标为.NET框架的语言被编译成IL代码,然后汇编成字节码。
具体过程是:C#或者VB这样遵循CLI规范的高级语言,被先被各自的编译器编译成中间语言IL。等到需要真正执行的时候,这些IL会被加载到运行时库,也就是CLR中,由CLR动态编译(JIT)成汇编代码然后在执行。
JIT是什么?just-in-time compiler,即时编译器。它将IL翻译成汇编语言,它自身会对运行环境做出许多假定,从而进行自己的优化方案。
比如第一次调用一个方法时,JIT会把遇到的IL代码进行验证+编译,最后放进内存中。方法仅在首次调用时才会有一些性能损失,以后对该方法的所有调用都以本机代码的形式全速运行。
Mono是什么?是支持.net跨平台的一种方式。因为.net本身不支持跨平台只能运行在Windows上,所以需要一个跨平台的第三方.net库,这就是Mono。
mono作为一个中间层将IL代码的处理分出好多个分支,分别对应不 ...
C#精要 - 反射篇
反射反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。
Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。
MethodInfo包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。
反射:反射提供了封装程序集,模块和类型对象,可以用反射动态地创建类型的实例,将类型绑定到现有对象,或者从现有对象类型里获取类型,然后调用类型的方法或访问字段和属性。
序列化:将对象转换为另一种媒介传输的格式过程。如,序列化一个对象,用Http通过internet在客户端和服务器之间传递该对象,在另一端用反序列化从该流中重新得到对象。
C#精要 - 委托与事件篇
委托和事件的区别是什么?委托本质是一个继承自System.MulticastDelegate的类;而事件是一个类型成员,是对委托的封装,就和属性是对字段的封装一样。
事件通过event关键词来定义。是对委托的封装。
为什么封装?为了让委托链的意义,从一个方法执行队列变成一个可订阅、可通知(触发)的中介。
怎么封装的?随便在类内定义一个public事件,再查看IL代码多帮我们做了什么:
1.生成一个私有的委托字段(没错还是委托链实现的)
2.生成add和remove方法,内部处理是对生成的委托字段进行Delegate.Combine、Delegate.Remove。
怎么设计?举个例子的话,WPF的画面交互事件用的EventHandler其实就是一个sender加一个args参数,自定义可以如下的:
1delegate void MyEventHandler(EventSender sender,MyEventArgs e);
委托委托本质是一个继承自System.MulticastDelegate的类,所以像类一样使用即可。
新建一个委托发生了什么?当你写delegate的时候,编译 ...
C#精要 - 常用数据结构篇
数组最基本的数组类型。
真实类型所有数组类型都隐式从System.Array抽象类派生,System.Array又从Object派生,所以数组都是引用类型。Array实现了IEnumerable、ICollection、IList接口。
特点在内存中是连续存储的,所以它的索引速度非常快。
初始化在new的时候,就必须指定它的Length大小。
数组单个元素的类型:
如果是值类型比如Int32,就会在托管堆上分配100个未装箱Int32所需的内存块,并给每个Int32实例都附上default值0;如果是引用类型比如Control,就会在托管堆上分配50个Control引用的内存块,并给每个引用都附上null。
扩容无法动态扩容,只能手动调用接口Array.Resize (ref T[] array, int newSize)。
内部创建新数组,使用Array.Copy将原数组拷贝到新数组中,再修改传入指针指向新数组。如果新Length还不如原数组Length大,会采用新Length,多的直接截断不要了。
查找接口Array.Find (T[] array, Predicate<T& ...