unity学习-渲染优化

cpu与gpu的区别

cpu:什么都干,主要处理代码的逻辑与传递信息,将需要DrewCall传递进gpu

gpu:主要处理渲染方面,实现DrewCall

层级细节LOD技术

我们在unity中一个模型如果距离远了看起来就会模糊,但是它实际上是按照原样来进行渲染的,那我们可以在距离他一定距离的时候将模型替换为粗糙一些的也看不出来,这时候我们可以用LOD组件,LOD组件分为4个档次,每个档次可以放置一个模型,当距离远的是后模型会自动替换,设定的距离可以调整

                遮挡剔除

unity中,我们还可以使物体在视野内才存在,不在视野内的物体不做渲染

具体操作如下:

1,选中进行遮挡剔除的物体

2,在static中选择Occluder Static(遮挡静态)

3,在windos中选择Occlusion Culling

4,选择Occluder Static,点击Back(生成遮挡剔除的数据)

5,选中Cameras,然后选择场景中的主相机

在unity中光照是非常消耗电脑渲染性能的,我们可以在制作的时候打光一次,然后将打上物体的光照变为物体贴图模拟出打光的效果

具体操作:

选择需要烘培的光源将Mode修改成Baked(烘培)

1,点击Static中的Lightmap

2,点击windos中的Lighting

3,在Debug settings中将自动烘培取消。然后点击Cancel进行烘培

合并mesh

在一个物体下会有很多子物体,每个子物体就是一次渲染调用,我们可以通过将子物体合并来达到减少渲染调用次数的目的

我们需要通过代码实现

void Meshhb()
{
    MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
    //创建一个数组放置获取到的mesh子物体
    CombineInstance[] cb=new CombineInstance[meshFilters.Length];
//创建一个合并类数组放置需要合并的物体
for(int i=0;i<meshFilters.Length;i++)
    {
        cb[i].mesh = meshFilters[i].sharedMesh;
        //将获取到的子物体挨个赋值到合并专用类的数组中
        cb[i].transform = meshFilters[i].transform.localToWorldMatrix;
        //将子物体的矩形获取到合并类数组中的物体上

    }
    Mesh ms = new Mesh();//设置一个物体放置合并后的mesh物体
    ms.CombineMeshes(cb);//进行合并
    GetComponent<MeshFilter>().sharedmesh = ms;//将MeshFilter组件获取到然后设置mesh物体
}

这是一个方法,目的是获取到目标的子物体,然后将子物体合并,然后将合并后的物体赋值回目标

我们需要在目标身上创建一个MeshFitter,然后在代码中获取到这个组件将合并后的mesh赋值给他

启动工程后就会在原对象旁边创建一个对象,形状与原对象相同,不同的是所有子对象全部融合为一个对象了

资源池

资源池的作用是创建一个列表用来放置需要重复生成的对象(例如子弹),如果每次都生成一个新的子弹对象那么就会出现很多次渲染和销毁调用,我们可以建立一个资源池放置一定数量的物体,将物体设置为不启用状态,建立一个列表放置这些物体

public int Count = 30;
public GameObject wuti;//放置一个放入资源池的物体
private List<GameObject> list = new List<GameObject>();
//创建一个列表放置资源池中的物体
// Start is called before the first frame update
void Start()
{
    uplist();//初始化资源池
}
void uplist()//初始化资源池的方法
{
    for (int i = 0; i < Count; i++)
    {
        GameObject go = GameObject.Instantiate(wuti);
        //将物体创建出来
        list.Add(go);//将创建出来的物体放入列表
        go.SetActive(false);//将物体禁用
        go.transform.parent = this.transform;
        //将物体放置在主物体下面变成子物体
    }
}

这样资源池就创建好了,后面我们需要创建一个方法用来调用资源池

public GameObject getwuti()//将物体调用的方法
{
    foreach (GameObject go in list)
    {
        if (go.activeInHierarchy == false)//如果遍历到的物体此时为禁用状态
        {
            go.SetActive(true);//将状态改为启用
            return go;//返回出方法
        }
        
    }
    return null;
}

在发射子弹的脚本中获取到这个资源池类,在发射的时候调用资源池方法,将方法返回的物体设置给需要发射的物体

过几秒后再将物体的的状态设置为禁用放回资源池等待下次调用

猜你喜欢

转载自blog.csdn.net/2401_84659046/article/details/142765506