Unity优化

举报
爱上游戏开发 发表于 2022/07/01 23:58:39 2022/07/01
【摘要】 推荐阅读:  我的CSDN 我的博客园 QQ群:704621321 我的个人博客 Unity 优化(一) ------ 优化前了解以及...

推荐阅读:

Unity 优化(一) ------ 优化前了解以及方向

FPS:画面每秒传输帧数,,要避免动作不流畅的最低是30;值越大性能越好
CPU:计算每帧需要消耗的时间,值越低说明计算越快,值越小性能越好
Batches:将某些DrawCalls合并,数量为合并后DrawCall的数量。
Tris:三角面
Verts:顶点
SetPass call:Shader中Cpu每次运行Pass之前都会产生一个SetPass call。

Unity 优化(二) ------ 资源优化

长时间音乐使用Mp3格式(使用压缩格式),例如:背景音乐等
短时间音乐使用wav格式(不使用压缩格式),例如:音效
在这里插入图片描述

减少冗余资源和重复资源
A、Resources目录下的资源不管是否被引用,都会打包进安装包
不使用的资源不要放在Resources目录下
B、不同目录下的相同资源文件,如果都被引用,那么都会打包进资源包,造成冗余
保证同一个资源文件在项目中只存放在一个目录位置
资源优化:使用UWA工具
渲染优化(GPU)和代码优化(CPU)
GPU:包括场景渲染和灯光处理等
CPU:数值计算

LOD——层级

当模型离视野近时,显示比较精细的模型,离视野比较远时显示比较粗糙的模型。
实现方法:
新建一个空物体,添加LOD Group组件,将模型拖进精细度按下图提示拖进对应位置,可根据实际情况调节每个LOD的占比。
在这里插入图片描述

遮挡剔除

目的;降低DrawCall
原理:在摄像机视野内的物体显示,在视野外的物体不显示。
实现方法:
(1)在场景中创建很多物体(方便观察)。全选中—点击Static—Occluder Static
[外链图片转存失败(img-DedDmHb2-1567147525008)(https://img.hacpai.com/file/2019/08/image-ec9a4dd6.png)]
(2)点击Windows—Occlusion Culling
image.png
image.png
(3)选择指定相机用于遮挡剔除计算
image.png

光照贴图

目的:降低Batches
实现方法:
(1)搭建好场景,选中场景中所有需要被光照的物体—点击Static—LightmapStatic
image.png
(2)点击Windowa—Lighting—Settings
image.png
(3)选择需要被烘焙的光源,将模式选择烘焙模式
image.png
(4)Scene—取消勾选—Generate Lighting
image.png
(5)选择烘焙后,下方是烘焙进度
image.png
(6)选择所有被烘焙的光源,取消Light勾选
image.png
这时还能看见光照效果,这时因为使用烘焙,生成了光照贴图
image.png
注意:如果觉得光照强度过强,在(4)前可修改
Light组件中Indensity值,值越低,光照越暗

合并Mesh

要求合并的mesh使用相同的材质。
实现方法:
(1)创建一个空物体MeshCombine,并为其创建几个子物体,子物体层级任意
image.png
(2)新建脚本并挂在到(1)中的空物体MeshCombine上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MeshCombine : MonoBehaviour {

	// Use this for initialization
	void Start () {
        CombineMesh();
	}
    void CombineMesh() 
    {
        MeshFilter[] filters = GetComponentsInChildren<MeshFilter>();//获取空物体下所有子物体的MeshFilter组件并保存为一个数组
        CombineInstance[] combiners = new CombineInstance[filters.Length];//unity提供的一个类,用于处理合并的实例
        //将filters的一些属性设置給combiners
        for (int i = 0; i < combiners.Length; i++) 
        {
            combiners[i].mesh = filters[i].sharedMesh;
            combiners[i].transform = filters[i].transform.localToWorldMatrix;//这里的transform不是一个组件而是一个矩阵转换,用于世界坐标与局部坐标之间的转换
        }
        Mesh finalMesh = new Mesh();
        finalMesh.CombineMeshes(combiners);//合并mesh
        GetComponent<MeshFilter>().sharedMesh = finalMesh;//将合并后的Mesh赋值到父物体上

    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

(3)为(1)中的空物体MeshCombine 添加两个组件:
MeshRender组件:负责渲染
MeshFilter组件:用于存放合并后的mesh
并未MeshRender组件选择一个需要的材质。
(4)游戏运行,会将MeshCombine下的所有子物体中的Mesh合并并赋值到MeshCombine物体上,因此场景中将会出现两个一模一样的mesh,这时在游戏运行时可直接删除其下的子物体,这时可明显看见Batches减少。

ObjectPool

对象池的使用可以说是非常常见。直接上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : MonoBehaviour {

    public int objCount=5;//对象池中该类对象初始生成的个数
    public GameObject buttlePreb;//需要实例化的预制
    private List<GameObject> poolList = new List<GameObject>();//存放对象

	void Start () {
		InitPool();
	}
    //初始化对象池
    void InitPool()
    {
        for (int i = 0; i < objCount; i++) 
        {
            GameObject go = Instantiate(buttlePreb);//实例化对象
            poolList.Add(go);//将实例化的对象添加到对象次
            go.SetActive(false);//设置为隐藏—即未被使用
        }
    }
    //从对象池中取对象
    public GameObject ShowObj()
    {
        foreach (GameObject go in poolList)
        {
            if (!go.activeInHierarchy)
            {
                go.SetActive(true);
                return go;
            }
        }
        return null;
    }
    //使用协程,使得对象生成后等待指定时间隐藏—即放回对象池
    public IEnumerator HideObj(GameObject go)
    {
        yield return new WaitForSeconds(3);
        go.SetActive(false);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

使用对象池:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class startBuntle : MonoBehaviour {

    private ObjectPool objPool;

	void Start () {
        objPool = GetComponent<ObjectPool>();
	}
	
	void Update () {
        if (Input.GetKeyUp(KeyCode.K)) 
        {
            GameObject go = objPool.ShowObj();
            if (go != null) 
            {
                //对象次还有可用对象
                go.GetComponent<Rigidbody>().velocity = transform.forward * 30;
                StartCoroutine(objPool.HideObj(go));
            }
        }
	}
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

文章来源: unity3d.blog.csdn.net,作者:爱上游戏开发,版权归原作者所有,如需转载,请联系作者。

原文链接:unity3d.blog.csdn.net/article/details/100146530

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。