读一读

Unity中自带的Plane的顶点个数是很多的,经过打印得出Plane的顶点个数为121个,对于要实现一些简单的放一个图片的Plane来说这有点浪费资源了,所以这些简单的只是显示一张图片的Plane可以自己创建出来,只使用4个顶点。

using System.Collections.Generic;
using UnityEngine;

public class CheckPlane : MonoBehaviour {
	void Start () {
        Mesh m = this.GetComponent<MeshFilter>().mesh;
        List<Vector3> list = new List<Vector3>();
        m.GetVertices(list);

        //Unity自带的Plane的顶点个数为 121
        Debug.LogError("顶点的个数为:" + list.Count);

        CreatPlane();
    }

    void CreatPlane()
    {
        Mesh m = new Mesh();
        GameObject go = new GameObject("Haha");
        MeshFilter f = go.AddComponent<MeshFilter>();
        f.mesh = m;

        Vector3[] array = new Vector3[4];//顶点坐标
        Vector3[] array2 = new Vector3[4];//顶点面法线
        Color[] array3 = new Color[4];//顶点颜色
        Vector2[] array4 = new Vector2[4];//uv坐标
        int[] array5 = new int[6];//三角型索引
        array[0] = new Vector3(-1f, 1f, 0f);//顶点坐标
        array[1] = new Vector3(1f, 1f, 0f);
        array[2] = new Vector3(-1f, -1f, 0f);
        array[3] = new Vector3(1f, -1f, 0f);
        array2[0] = new Vector3(0f, 1f, 0f);//顶点面法线
        array2[1] = new Vector3(0f, 1f, 0f);
        array2[2] = new Vector3(0f, 1f, 0f);
        array2[3] = new Vector3(0f, 1f, 0f);
        array3[0] = new Color(1f, 1f, 1f);//顶点颜色
        array3[1] = new Color(1f, 1f, 1f);
        array3[2] = new Color(1f, 1f, 1f);
        array3[3] = new Color(1f, 1f, 1f);
        array4[0] = new Vector2(0f, 0f);//uv坐标
        array4[1] = new Vector2(1f, 0f);
        array4[2] = new Vector2(0f, 1f);
        array4[3] = new Vector2(1f, 1f);
        array5[0] = 0;//三角型索引
        array5[1] = 1;
        array5[2] = 2;
        array5[3] = 2;
        array5[4] = 1;
        array5[5] = 3;
        m.vertices = array;
        m.normals = array2;
        m.colors = array3;
        m.uv = array4;
        m.triangles = array5;

        Shader shader = Shader.Find("Standard");//根据项目需要,使用Shader
        Material mat = new Material(shader);
        go.AddComponent<MeshRenderer>().material = mat;

        //打印下顶点个数
        List<Vector3> list = new List<Vector3>();
        m.GetVertices(list);
        Debug.LogError("自己创建的顶点个数:" + list.Count);
    }
}


blob.png


Plane[] planes = GeometryUtility.CalculateFrustumPlanes(mainCamera);//获取该相机的剪裁锥体的6个面
Bounds bounds = target.GetComponent<Collider>().bounds();//获取物体的碰撞盒子
bounds.Expand(2.0f);//扩大一下这个碰撞盒子
bool isIn = GeometryUtility.TestPlanesAABB(planes, bound);//判断是否在相机视野内
target.SetActive(isIn);


扩大碰撞盒子是为了避免模型物体突然出现在相机视野的情况,因为视野是会移动的,留点边界预留区保留效果。


对于频繁分配小块内存的可以在固定帧数的时候主动调用GC回收。

对于内存分配不频繁的且可以在暂停时才回收的,可以在启动时使用空物体等来扩大堆空间,来扩充到游戏暂停前(GC回收垃圾)空闲的堆空间不被填满。然后在暂停的时机调用GC回收。

具体优化情况,参考profiler的统计数据。


在经常调用的函数或则是帧函数中要减少临时变量的使用,例如一个函数需要返回一个数组,而这个函数需要经常调用时,函数里面会经常的为临时的数组分配内存,下一秒又不用了,产生了大量垃圾,增加GC的负担。所以,对于这类型的应该使用一个全局的变量来通过参数的形式来传入引用,然后修改对应的值来再返回。


内存管理器会在空闲堆空间不够用时去检测没有被引用的内存,然后去回收,然而,当这些垃圾数量很多的时候就会造成回收耗费大量资源从而影响游戏的性能。所以,有一个办法就是保证内存中的垃圾不要过多,我们可以定时的、在合适的时机去主动调用GC去回收。

if (Time.frameCount % 60 == 0) {
    System.GC.Collect();
}

对于那些复杂点的,但是又不需要每一帧都去执行的代码,我们可以使用InvokeRepeating来指定每秒调用方法的次数,从而节省性能。

void Start () {
    InvokeRepeating("Repeat", 0, 0.2f);
}

int a;
void Repeat() {
    for (int i = 0; i < 10000000; i++)
        a = i * i;
}

经过测试,如果在Update中去大量的(10W次)去寻找GameObject或获得组件,帧率会有大幅度的下降,特别时Find等的操作方法。在Update中执行普通的运算10W次基本上不影响帧率,所以说Find和GetComponent等方法的执行时具有一定的耗时的,所以最好就是将这些放到Start中,通过引用把查找获取的结果保存下来。

private GameObject cube;
void Start () {
    cube = GameObject.Find("Cube");
}

当我们要为一个Label每帧都赋值一个string时,就会产生垃圾,引起GC的回收,影响性能和分析不正确。

可以使用一个固定的数组列举所有的情况,用内存来减少垃圾生成从而调用GC


打开profiler分析游戏性能,如果开启了垂直同步vsync,它会主导profiler的Cpu图形。应打开Edit/Project Settings/Quality调整

在profiler中可以看到CPU图形上老是有突起出现,这些是因为Editor的关系,当你去选择一些东西的时候会导致调用CameView.GetMainGameViewRenderRect

我们可以导出.exe,设置DevelopmentBuild和Autoconnect Profile,运行后,Unity将自动捕捉分析数据。


使用图片压缩,图片的格式对大小影响不大,使用mipmap将会3倍大小。代码能不用System就不用,这会加大数M包的大小。使用a subset .Net2.0,如果可以。