CS003-2-2-perfermance

44、shader预热

a. 避免游戏运行时shader编译导致的卡顿

b. shader编译过程,着色器代码需要被编译成gpu能够理解的机器码。也就是将高级语言hlsl编写的shader编译成gpu可以直接执行的指令。在编译的过程中,还会有编译优化,展开循环,内联函数,以及对代码进行重新排序等。

45、C#中弱引用

a. 允许引用一个对象,但不阻止该对象被gc。

b. 使用举例

复制代码
public class WeakReferenceTest : MonoBehaviour
{
    WeakReference weakRef;
    // Start is called before the first frame update
    void Start()
    {
        // 创建一个对象
        var myObject = new TestWeakReferenceObj();
 
        // 创建弱引用
        weakRef = new WeakReference(myObject);
 
        // 解除强引用,只保留弱引用
        myObject = null;
 
        // 通过弱引用访问对象
        if (weakRef.IsAlive)
        {
            var obj = weakRef.Target as TestWeakReferenceObj;
            obj.DoSomething();
        }
        else
        {
            Debug.Log("对象已被回收");
        }
    }
 
    // Update is called once per frame
    void Update()
    {
        // 通过弱引用访问对象
        if (weakRef.IsAlive)
        {
            var obj = weakRef.Target as TestWeakReferenceObj;
            obj.DoSomething();
        }
        else
        {
            Debug.Log("对象已被回收");
        }
    }
}
 
class TestWeakReferenceObj { 
    public void DoSomething()
    {
        Debug.Log("对象没有被回收");
    }
}

C. 泛型写法

复制代码
public class WeakReferenceTest : MonoBehaviour
{
    WeakReference<TestWeakReferenceObj> weakRefGeneric;
    // Start is called before the first frame update
    void Start()
    {
        weakRefGeneric = new WeakReference<TestWeakReferenceObj>(new TestWeakReferenceObj());
 
        if (weakRefGeneric.TryGetTarget(out TestWeakReferenceObj obj))
        {
            obj.DoSomething();
        }
        else
        {
            Debug.Log("对象已被回收");
        }
    }
 
    // Update is called once per frame
    void Update()
    {
        if (weakRefGeneric.TryGetTarget(out TestWeakReferenceObj obj))
        {
            obj.DoSomething();
        }
        else
        {
            Debug.Log("对象已被回收");
        }
    }
}
 
class TestWeakReferenceObj { 
    public void DoSomething()
    {
        Debug.Log("对象没有被回收");
    }
}

d. 适用场景,缓存大型对象,但允许gc在需要时回收它们。

e. 性能上,频繁检查弱引用是否存在可能影响性能。

46、贴图的格式

a. read/write,纹理资源的内存占用是计算在显存中的,也就是传向gpu端的部分。而开启read/write enabled选项的纹理资源还会保留一份在cpu端,从而造成该资源内存占用翻倍。

b. mipmap,当一张纹理开启mipmap时,它的内存占用会上升为原始数据的1.33倍。对于3d对象,比如场景中的地形、物件或人物,其纹理的mipmap功能是建议开启的,可以在运行时降低带宽。对于2d项目或ui界面资源,建议将对应的mipmap功能关闭,从而避免不必要的内存开销。

47、网格资源

Unity移动端游戏性能优化简谱之 常见游戏内存控制 - 知乎

a. 顶点和面数

v是顶点数,t是三角面数,不同part,比如脸部、头部、身体、脚网格加起来,大致有个概念。

顶点数在2w个,三角面在3w左右。

nami模型的复杂度举例:

v 5295 t 7732

v 3544 t 4607

v 4063 t 6275

v 8288 t 12836

2w顶点 31450三角面

luffy模型的复杂度举例:

v 2403 t 3906

v 3825 t 5736

v 7734 t 12755

v 1150 t 1769

v 644 t 642

v 1176 t 1456

16932顶点 26264 三角面

b. 顶点属性,去除不需要的顶点属性

c. read/write enabled,一般而言,不需要在cpu端进行修改的网格是不需要开启read/write的。可以在编辑器中通过api修改这些网格的read/write属性,或者编辑器面板中直接设置。

48、shader.parse

a. shader.parse将shader源代码字符串解析为unity可以识别的shader对象,但不会编译为gpu程序。

b. shader.creategpuprogram,显示编译shader代码为gpu可执行的程序,生成渲染管线中使用的底层指令。creategpuprogram编译shader可能会引起卡顿。

49、unsafe和fixed

a. 在unity中,以下情况通常需要fixed。处理NativeArray时。

b. unsafe代码块,不一定总是需要fixed,但当你需要通过指针操作托管堆撒上的对象时,就必须使用fixed来固定内存。

复制代码
unsafe void ProcessArray(int[] managedArray)
{
    fixed (int* ptr = managedArray) // 必须fixed,因为数组在托管堆上
    {
        for(int i = 0; i < managedArray.Length; i++)
        {
            ptr[i] *= 2;
        }
    }
}

c. fixed使用访问托管对象的,会"钉住"对象,阻止gc在固定期间移动对象。

d. 不需要fixed的举例

复制代码
unsafe void StackAllocExample()
{
    int* array = stackalloc int[10]; // 栈上分配,不需要fixed
    for(int i = 0; i < 10; i++) 
    {
        array[i] = i;
    }
}

50、astc

a. 区块编码

最简单的块编码,从定义两种颜色的"端点"开始。端点定义了两种颜色,通过在两种颜色之间进行插值生成许多额外的颜色。

b. astc是有损压缩格式。

c. astc使用块压缩。所谓的块压缩,即将贴图分为固定大小的块,每个块内的颜色值压缩在一起。当随机访问一个贴图的像素时,只要计算其所属的块,将块解压缩即可获得颜色值。这样就充分利用gpu的并行处理能力。

d. 原理Unity ASTC贴图压缩格式探秘 - 知乎

astc采用梯度渐变gradient存储颜色值。每个block会存储一对终点颜色(end-point colors),每个纹素存储一个插值权重,根据权重插值end-point colors即可获得原始颜色。

e. astc支持4x4到12x12的block大小,block大小以像素为单位。8x8的block即表示块对应原始贴图里width和height为8x8 texels区域。

f. 一个block的压缩后,大小固定128bits。也就是不管4x4、5x5、8x8最后压缩都是在128位内。所以block越大,压缩越严重,失真越严重。

相关推荐
Q_970956391 分钟前
java+vue+SpringBoo足球社区管理系统(程序+数据库+报告+部署教程+答辩指导)
java·开发语言·数据库
要开心吖ZSH6 分钟前
微服务架构的演进:迈向云原生
java·微服务·云原生
为了更好的明天而战25 分钟前
Java 中的 ArrayList 和 LinkedList 区别详解(源码级理解)
java·开发语言
JosieBook1 小时前
【Java编程动手学】Java中的数组与集合
java·开发语言·python
qq_589568101 小时前
element-plus按需自动导入的配置 以及icon图标不显示的问题解决
开发语言·javascript·ecmascript
N_NAN_N1 小时前
类图+案例+代码详解:软件设计模式----单例模式
java·单例模式·设计模式
lsx2024061 小时前
SQLite Select 语句详解
开发语言
weixin_399380691 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
Dovis(誓平步青云)1 小时前
基于探索C++特殊容器类型:容器适配器+底层实现原理
开发语言·c++·queue·适配器·stack
lang201509281 小时前
Reactor ConnectableFlux支持多订阅者
java·网络