[关闭]
@daaoling 2017-02-17T13:49:30.000000Z 字数 2613 阅读 2949

Unity

一种高性能的使用顶点动画的战斗飘血方案

起源

之前项目如果使用Ngui做飘血功能,一旦同屏超过几百个飘血就开始卡了, 采用了对象池也没有很好的好转, 查看了一下源码主要是两点
1.ngui在对动态的物体的时候都会有重新绘制drawcall
2.每一帧对物体进行插值计算消耗了大量cpu时间

思考了一下 针对以上缺陷,我图集还是采用ngui的, 因为要控制drawcall, 但是考虑自己使用自定义重构mesh生成, 然后根据曲线插值位置, 缩放和alpha, 那么我就不需要每次变动重新绘制drawcall了, 可是这样一来, 在unity4.7 版本上会出现dynamic batch 失效的情况, 导致还不如ngui的性能, 最严重的时候甚至到了 5 fps
我思考可能不同时期缩放不一样导致的

Generally, objects should be using the same transform scale.
The exception is non-uniform scaled objects; if several objects all have different non-uniform scale then they can still be batched.

那么我就想到了顶点动画才进行插值运动,运用vertex的别的通道来存储其动画信息。
但是本身的话如果一个pop 建立一个mesh的话drawcall控制不住。那么我采用 update 放入当前这一帧所需要绘制的所有 pop mesh的顶点信息, 在lateupdate把这一帧的所有顶点信息用一个mesh绘制。

有人问为什么不在材质上设置参数呢? 这样一来不就一个 pop 对应一个材质了嘛,drawcall 不就上去了?

这样一来就解决了以上两个问题,不用cpu插值, 动态物体drawcall只有一次

思路来自于此 http://www.cnblogs.com/lxzCode/p/4780360.html

设计

自定义Mesh

哈哈,是不是很眼熟

if (mFilter == null) mFilter = gameObject.GetComponent<MeshFilter>();
if (mFilter == null) mFilter = gameObject.AddComponent<MeshFilter>();

// Create the mesh
if (mMesh == null)
{
    mMesh = new Mesh();
    mMesh.hideFlags = HideFlags.DontSave;
    mMesh.name = "Mesh";
    mMesh.MarkDynamic();
}

mMesh.Clear();
mMesh.vertices = verts.ToArray();
mMesh.uv = uvs.ToArray();
mMesh.colors32 = cols.ToArray();

mMesh.normals = vertex1.ToArray();
mMesh.tangents = vertex2.ToArray();
mMesh.uv1 = vertex3.ToArray();

int triangleCount = (vertex_count >> 1) * 3;
mMesh.triangles = GenerateCachedIndexBuffer(vertex_count, triangleCount);
mFilter.mesh = mMesh;

if (mRenderer == null) mRenderer = gameObject.GetComponent<MeshRenderer>();
if (mRenderer == null) mRenderer = gameObject.AddComponent<MeshRenderer>();

顶点动画 shder

struct appdata_m 
{
    float4 vertex : POSITION;
    float3 vertex1 : NORMAL; ///这里记录第二帧的位置信息
    float4 vertex2 : TANGENT;///这里记录第三帧的位置信息
    float2 vertex3 : TEXCOORD1;///这里记录第四帧的位置信息

    float2 texcoord : TEXCOORD0;

    fixed4 color : COLOR;
};

v2f_m vert (appdata_m v)
{
    v2f_m o;

    _CurTime = _Time.y - _StartTime;

    if(_CurTime <= v.vertex1.z) {
        _vertex1 = float3(v.vertex1.x, v.vertex1.y, 0);
        _Factor = _CurTime / v.vertex1.z;
        _vec = lerp(v.vertex.xyz, _vertex1, _Factor);
        _alpha = lerp(v.color.a, v.color.r, _Factor);
    }
    else if (_CurTime <= v.vertex2.z) { 

        _vertex1 = float3(v.vertex1.x, v.vertex1.y, 0);
        _vertex2 = float3(v.vertex2.x, v.vertex2.y, 0);

        _Factor =  (_CurTime - v.vertex1.z) / (v.vertex2.z - v.vertex1.z);

        _vec = lerp(_vertex1, _vertex2, _Factor);
        _alpha = lerp(v.color.r, v.color.g, _Factor);
    } 
    else {

        _vertex2 = float3(v.vertex2.x, v.vertex2.y, 0);
        _vertex3 = float3(v.vertex2.w, v.vertex3.x, 0);

        _Factor =  (_CurTime - v.vertex2.z) / (v.vertex3.y - v.vertex2.z);

        _vec = lerp(_vertex2, _vertex3, _Factor);
        _alpha = lerp(v.color.g, v.color.b, _Factor);
    }
    ...
    return o;
}

接下来只要mesh给予带运动轨迹的顶点信息,采用VertexAnimation Shader即可

完结

魅族测试

image_1b34s3od6kqb1j1kktfjee1mc99.png-87.9kB

源码

https://git.oschina.net/daao/Vertex_HUD
or
https://github.com/daaoling/Vertex_HUD

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注