《Unity3D高级编程:主程手记》 摘录
最近看了《Unity3D高级编程:主程手记》这本书,作者陆泽西 。摘录部分要点,仅供个人学习使用,如侵删。◆ 第1章 软件架构
◆ 1.2 软件架构的思维方式
>> 如果要问软件研发、架构设计中最重要的能力是什么,我会毫不犹豫回答是抽象能力。
>> 第一种:分层思维
>> 第二种:分治思维
>> 第三种:演化思维
◆ 第2章 C#技术要点
◆ 2.6 排序算法
>> 在平时的编程工作中,排序算法和搜索算法最常用。
◆ 2.6.1 快速排序算法
◆ 2.6.2 最大最小堆
◆ 2.7.2 二分查找算法
◆ 2.8.6 程序运行原理
>> 业务逻辑的优化很大程度上都是围绕着以下环节展开的:如何利用好CPU缓存命中率、如何减少内存分配和卸载次数,以及如何利用好多线程,让多个线程协作顺畅,并且能分担任务。
◆ 第5章 3D模型与动画
>> 下面就来介绍在项目中制定美术资源规范时可以用到的几个方法。
(1)根据运用的场景来确定
>> 第三人称视角的RPG,由于视角是第三人称的自由视角,同时看到的场景范围会更多一些,视角下的模型数量也会比较多,因此角色模型的面数要控制在3000面以下,骨骼数量控制在30个以下,建筑模型面数因大小差异而无法统一,可以分成大型建筑7000面以下,中型建筑5000面以下,小型建筑3000面以下,小部件则控制在1000面以下。贴图也需要更多的限制,最好为512×512像素及以下,角色和中大型模型主贴图为512×512像素,副贴图为256×256像素,小型和小部件贴图控制在128×128像素及以下。
>> (2)使用反推计算来得出规范
>> 对于一些模型物体大小差异比较大的、无法统一模型与贴图面数的,可以使用全场景总面数来控制
>> 贴图大小同样也可以按照这种方法进行规范,我们先设定一个总体内存,例如设定了一个不超过500MB的内存,通常内存中包括资源内存、业务逻辑内存、引擎逻辑内存、第三方插件内存,我们来为各部分占用的内存做个假设
>> 除了通过占用内存的大小来指定规范外,也可以使用总张数和总尺寸大小来进行规范
◆ 5.2.1 网格模型的基础知识
>> 2. Unity3D模型中子网格的意义
>> 在渲染引擎的时候,每个子网格都要匹配一个材质球来做渲染,说白了,一个子网格本身就是一个普通的模型,它由很多个三角形构成,也需要材质球支持以达成渲染。
>> 美术人员在制作3D模型时,为什么不把网格编成一个,而要制作成多个子网格?
>> 第一个原因是,美术人员在制作3D模型的时候,希望一个模型中的一部分网格用一种材质球来表现效果,另一部分网格则用另一种材质球来表现效果,这时就需要将模型拆分开来。因为一个网格只能对应一个材质球,一个材质球只能表现一种效果,当需要表现多种完全不同的效果时就需要拆分。
>> 第二个原因是,模型中的某部分贴图在众多模型中共同使用的频率比较高,为了不重复制作以减少重复劳动,原本可以作为一个整体的模型会将公共材质部分单独拆分出来让这一部分模型使用同一个材质球。
>> 第三个原因是,在制作动画时,由于动画过于复杂,如果使用同一个模型去表现,则骨骼的数量就会成倍增加。为了能够更好地表现动画,也为了能降低骨骼的使用数量,要拆分出一部分模型,让它们单独成为模型动画的一部分。
>> 从功能上来看,多个子网格比单个网格要灵活得多。但它也有缺点,由于每个子网格都有材质球,导致子网格越多,增加的渲染管线调用(drawcall)也越多。网格中存在多个子网格,在动作和拆分材质球渲染上确实很有优势,但无法与其他网格合并,这会导致优化的一个重要环节被阻断
◆ 5.4.4 蒙皮骨骼动画
>> SkinnedMeshRenderer虽然也渲染模型,也从MeshFilter中提取模型网格顶点数据,但蒙皮网格主要用于渲染动画服务,所以蒙皮网格除了3D模型数据外,还有骨骼数据及顶点权重数据。
>> 骨骼动画是以顶点的骨骼权重数据来决定顶点受哪些骨骼点的影响的,
>> 骨骼点越多,网格就越复杂(顶点或面数很多),消耗的CPU就越多,因为网格里的顶点需要通过蒙皮算法来算出顶点的变化,一般情况下,这些都是靠CPU来计算
◆ 5.4.7 动画优化
>> 3D模型动画的优化方法和解决方案
>> 1.用着色器代替动画
>> 顶点着色器可以改变网格顶点的位置。
>> 除了顶点动画,还可以利用UV来制作动画
>> 用着色器代替动画的实质就是用GPU消耗来分担CPU的计算量,因为部分计算在GPU中会更高效
>> 2.离线制作加速动画
>> 3. GPU Instancing加速动画
>> 4.离线制作LOD动画与LOD网格
◆ 第6章 网络通信
◆ 6.4.4 多次请求时连续发送HTTP请求引起的问题
>> 那怎么在多请求连接的情况下保证顺序呢?
>> 解决方案1:多个连接同时发送请求,等待所有数据到齐后再调用执行逻辑
>> 解决方案2:逐个发起请求,保证顺序
>> 解决方案3:多连接与逐个发送混合使用
>> 解决方案4:合并请求,并逐个发送合并后的请求包
◆ 6.6 网络同步解决方案
>> 当前网络游戏中,网络同步解决方案有三种,即状态同步、实时广播同步、帧同步。三种方案不互相排斥,可以混合使用。
>> 同步方案的目标是在多人游戏中用最少的信息同步量来逼真地“模拟”其他玩家的一举一动,让我们在玩游戏的时候能看到其他玩家的位置、动作及状态
◆ 6.6.4 同步快进
>> 如何预测和模拟延迟部分的表现,以及快速同步落后很多帧的客户端画面,成了客户端解决同步问题的关键
>> 要解决这个问题,我们可以在执行帧逻辑时,采用每次执行N帧(N大于10)的方式来使画面快速推进,这样玩家既能看到动态的画面,又能快速地跟上最后的同步帧数据,同步完所有的帧数据后,再将执行速度恢复到正常
>> 内存快照的方式执行快进操作。
◆ 6.6.5 精度问题
>> 只要所有设备执行的帧数一致,执行的指令和时间点一致,执行的算法一致,就能得出相同的结果。
◆ 第8章 地图与寻路
◆ 8.1.1 长距离导航
>> 长距离导航通常发生在场景地图很大的情况下,当我们需要寻路的两点距离很长,中间有很多障碍物时,A星算法就会遇到瓶颈。
>> 可以把一些常用的路径在离线状态下计算好并放在数据文件中。
>> 将离线数据与实时计算的数据拼接,节省了很大的计算量,留给我们计算的仅是从起点到伪起点、从伪终点到终点的实时路径部分。
>> 为了让离线计算更快,为了缩短离线计算的路径,可在地图上多设置一些距离不是太长的导航点
◆ 8.1.7 寻路规则优化JPS
>> JPS(Jump Point Search)对A星的搜索规则进行了改造,即不再是搜索某个点附近的点,而是想要用拐点(跳点)来代替。
◆ 8.4.2 常规场景的性能优化
>> 贴图太多、宽带压力太大,主要是因为需要将内存的纹理复制到显存中才能在GPU中渲染,而且这样做显存的消耗也很大。
>> 显存只存在于主机和PC游戏中,在手机中没有显存的概念,手机设备中的显存都是内存内部的复制,即手机中会为GPU预留出一块用于渲染的内存块作为缓存。
>> 将片段着色器的计算量转移到顶点着色器中,就能节省很多GPU消耗。
◆ 9.2.2 渲染管线是什么
>> 安卓和iOS系统的架构决定了它们只能用内存来为GPU提供服务,因此,手机端中没有将数据复制到显存这个过程,它们使用的是同一个物理内存地址。除非要读/写这块内存的内容,才会将它们另外复制一份,以调节CPU与GPU之间的协作(三重缓存机制)。
◆ 10.1 渲染顺序
>> 渲染顺序是提高GPU效率的关键
>> Unity3D引擎在提交渲染时有这么一条规则,即对所有半透明物体的渲染都排在不透明物体的后面,这样就确保了半透明物体在不透明物体渲染完毕后才开始渲染,从而保证半透明物体的混合效果。
>> 不透明物体的排序与半透明物体的排序是相反的,因为半透明物体需要混合,必须先绘制远处的物体,这样混合的效果才正确。
>> Unity3D规定2500以下的索引号的排序规则是,可以根据摄像机的距离由近及远地渲染,2500以上的索引号的排序规则是根据摄像机的距离由远及近地渲染。
◆ 10.5 显存的工作原理
>> 图片大小、网格大小也会成为复制的瓶颈点,我们通常称它们为带宽压力。
>> 压缩纹理贴图、使用大小适中的纹理贴图、减少网格数据是优化性能的一个重要部分。
◆ 10.7 实时阴影是如何生成的
>> Unity3D在渲染时,首先会在当前着色器中找到LightMode为ShadowCaster的Pass,如果没有,则会在Fallback指定的着色器中继续寻找,如果还没有,则无法产生阴影,因为无论是传统的阴影投影还是屏幕空间阴影投影,都需要先产生阴影纹理图(Shadow Map)。
◆ 10.8 光照纹理烘焙原理
>> 烘焙需要用到模型的UV1数据,在导出模型时,如果没有加入UV1数据,则可能无法得到正确的烘焙结果。
>> 间接光照则描述了光线在物体表面之间的折射,增加了场景中的明暗变化以及光线折射的细节,提高了真实感。
◆ 10.10 着色器编译过程
>> 如果没有提前编译着色器而在场景中使用着色器,就会不断地有不同的着色器被实时编译,这是导致游戏卡顿的重要原因之一。 总结的不错 谢谢
页:
[1]