配置读取(难点)
配置文件在编辑器的StreamingAssets目录下,放置一个json格式的InitPlanes.json文件,作为配置文件。同时我们也在Resources文件夹下放这个文件,用在后面测试。
1234567891011121314151617181920212223242526272829303132{ "planes": [ { "planeId": 0, "level": 0, "attack": 5, "fireRate": 0.8, "life": 100 }, { "planeId": 1, "level": 0, "attack": 10, "fireRate": 0.6, "life": 120 ...
英雄选择和数据持久化
VS任务列表在C#代码中输入类似的注释
12//TODO: something to do//todo: something to do
然后打开Visual Studio的“任务列表”,快捷键“CTRL + ,T”,或者“视图——任务列表”,就能够显示所有在代码中标记的需要做的任务。
选择英雄部分我们希望选择一个英雄时,它的头像变亮,其他的头像变暗。
英雄头像选择每一个英雄头像都是一个Button,它们都动态挂载HeroItem脚本。这个脚本负责头像明暗的逻辑,并且声明一个回调,这个回调调用父级的方法,从而让每个英雄头像正确地变亮变暗。
12345678910111213141516171819202122232425262728293031323334using UnityEngine;using UnityEngine.UI;using DG.Tweening;using System;public class HeroItem : MonoBehaviour{ private Color defaultColor = Color.gray; privat ...
动态生成图集
动态图集的意义比如说MOBA类游戏,在进入对战场景时,我们需要选择英雄,配置技能,选择天赋和符文等,这些图标如果都事先打好了图集,在对战场景就会加载很多没有用的图标,而如果不打图集,就会增加很多drawcall,所以我们需要动态生成图集。
动态图集算法GitHub - DaVikingCode/UnityRuntimeSpriteSheetsGenerator: Unity – generate SpriteSheets at runtime!
Unity也提供了算法Unity - Scripting API: Texture2D.PackTextures (unity3d.com)
我们使用GitHub的项目。
核心代码AssetPacker类
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273//传入单张图片的路径,带拓展名,以及单张图片的自定义ID ...
UI管理
实现简易的UI管理,适合单机。
UIMgr12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576using System.Collections.Generic;using UnityEngine;public class UIMgr : NormalSingleton<UIMgr>{ private Canvas canvas; public Canvas Canvas => canvas; private Stack<string> uiStack = new Stack<string>(); private Dictionary<string,IView> viewsDic = new Dictionary<string,IView>(); ...
资源加载框架
项目地址National-fighter-jets: 全民飞机大战 (gitee.com)
框架基于Manager of Managers
资源格式规范工具资源导入 | ATAO2017,阿宅创造奇迹! (atao-blast.github.io)
用做UI的Sprite,导入选项中不要勾选“Enable Read/Write”和“Generate Mip Maps”,前者增大内存,后者会导致图片打包后模糊。
12345678910using UnityEditor;public class TextureImportSetting : AssetPostprocessor{ private void OnPreprocessTexture() { TextureImporter importer = assetImporter as TextureImporter; importer.textureType = TextureImporterType.Sprite; }}
拼UI摘要 ...
纹理压缩
颜色通道RGBA32代表四个通道总32bit,每个通道占8bit
RGBA16,每个通道占4bit
纹理压缩格式JPG:一种有损压缩不透明图片格式
PNG:一种无损压缩透明图片格式
Unity导入图片格式后,都会先转化成纹理格式。只有纹理格式才能被GPU解压和使用。
纹理压缩格式的选择Unity纹理详解:
Unity - Manual: Recommended, default, and supported texture formats, by platform (unity3d.com)
Unity提供Crunched DXT和Crunched ETC纹理格式,它们在原来的纹理压缩格式的基础上又使用Crunch压缩了一遍(也就是下面的BC6,BC7)。
PC建议使用二次压缩。在一张贴图的导入设置面板中的Default选项卡中,勾选“Use Crunch Compression”。Android和iOS选择ASTC。
如果是某些不得不清晰显示的大图,建议选择不压缩RGBA32等。而某些时候有些大图不需要清晰显示,但是又不是2的整数次幂的样式,可以单独打一张图集。
PC端对于具有Dir ...
UI图集
打图集的意义相同图集的UI图片可以合批,减少drawcall优化性能。
开启图集Project Settings——Editor——Sprite Packer——“Sprite Atlas”。我们测试时可以选择Always。
使用图集首先,确保Unity已经安装了2D Package。
准备一个文件夹用来保存图集,在文件夹中右键——2D——Sprite Atlas。然后根据图集内容取一个名字。
MasterMaster图集是主要集合,其中的Allow Rotation、Tight Packing、Alpha Dilation都是为了减小生成的图集的大小的优化选项。
我们点击面板上的“Objects for Packing”的加号,会发现弹出的选择面板中有提示
1t:sprite t:texture2d t:folder
中间列出了可以直接加进Packing的文件类型,也可以把整个文件夹放进来,比如输入t:folder Icon就能快速查询到名字为Icon的文件夹。注意,选择文件夹后,文件夹中的子文件夹内的图片也会被识别并加入到图集中。
VariantVariant图集需要引用Mast ...
UI其他优化
填充率我们打开Scene窗口的Overdraw,可以查看到每个UI界面的重复绘制情况。
由于显卡的填充率有限,过多的重复绘制肯定会影响性能。
注意要点UI的Image组件即使是全透明的也会增加Overdraw。
在设计UI时,尽量不要让UI元素相互覆盖。
在设计UI时,不要把UI分得太细。可以合并成一个图的尽量合并成一个。
圆形和不规则形状的UI,它们的原贴图一般都是方形的,可以对原贴图进行适当的裁剪优化。
优化
框型UI,使用九宫格。使用九宫格可以让框型UI中间部分镂空:
不规则图形,无法使用九宫格,也是可以镂空的,通过一些工具脚本。(待补充)
Mask,根据情况,可以使用自定义的Mask(比如圆形图片组件)
Unity对Text组件,有自带的Outline和Shadow效果,它们的原理只是简单复制Text,会大量增加顶点和三角面。从而增加填充率。所以对于文本,无脑选择TextMesh Pro。如果条件允许,也可以自己写一个文本Outline效果。(待补充)
UI和3D物体有的时候,当我们有些场景的物体使用OnRender等类似的函数时,在Game场景下物体已经不在Ca ...
Mask遮罩和RectMask2D
Mask基本知识Mask的原理是模板缓存。
Mask必须依赖一个Image组件。
一个单独的Mask(没有任何用来遮罩的子物体),也会产生2个drawcall。
用作Mask的Image,是无法与相邻的同材质的Image进行合批的,Mask会打断合批(因为Mask会使用特殊的材质)。同样地,Mask的子Image只能在Mask内部进行合批,和外部的Image无法合批。两个Mask使用的图片贴图ID相同的话,也能够合批。
Mask源码Mask自己本身产生两次drawcall的原因:
Mask在最开始设置模板缓存时,会产生一次drawcalll。
在Mask遍历完所有子物体执行完逻辑后,会还原一下模板缓存,这会产生第二次drawcall。
在Mask源码的GetModifiedMaterial方法内,写明了模板缓存的逻辑:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748/// Stencil calculation time!public virtual Ma ...
UGUI合批
UGUI渲染的顺序,就是在Hierarchy窗口中由上到下的顺序,也就是从后向前渲染,因为前面说过,UI是在透明物体的渲染队列当中渲染的。
合批规则在合批之前,UGUI按照下面的顺序对UI进行分类排序:
判断深度(Depth)——判断材质ID——判断贴图ID——判断渲染顺序(也就是在Hierarchy窗口中的顺序)
在UGUI当中,每个UI的Depth是自己计算的(NGUI是开发者自己填写)
经过上面的筛选,内部会生成一个排序后的List用于判断合批,如果发现在这个List内前后两个UI的材质ID和贴图ID相同,那么这些UI就进行合批(batch),在一次渲染中全部渲染出来。注意Hierarchy窗口内Canvas下UI的顺序和两个UI是否合批没有直接关系。
Depth生成UI分类排序的第一步,就是确定每一个UI的Depth。
首先,在同一个Canvas下,被关闭的UI的Depth数值为-1,从前面的UGUI源码中可以知道,Depth为-1的UI组件是不会被渲染的。
然后,在Canvas从上到下,越靠上的一般为背景,如果这个UI的“后面(里摄像机较远的一面)”没有其他需要渲染的UI ...