在安卓设备上,播放顶点动画

废话:

通常顶点动画可以用ABC或者点缓存动画插件来做,但是本人在工作当中遇到了一个需求就是将一个球体平滑过度成一个平面,我尝试过ABC插件去做,的确可以做,效果很好但是,当我打包的时候发现,ABC插件不支持在安卓设备上运行,而 MegaFiers这个插件制作这个效果又非常复杂,所以想,😔唉~自己写一个吧!

1.效果

Unity在安卓设备上播放顶点动画

2.原理:

改变Mesh的顶点位置实现变形,基本表达式:vertex[n]=V3(v3 1,v3 2,lerp);(这是个表达式,不是实际的代码!)

3.实现步骤:

1.在三维建模软件中制作模型顶点动画,导出ABC文件;

2.在Unity中安装ABC插件,读取ABC文件;

3.制作顶点数据采集工具,保存ABC文件每个Time帧的顶点数据信息;

4.保存ABC模型的Mesh,为了保证UV和顶点数量等信息统一;

5.unity在pg包中导入jobs,编写代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Jobs;
using Unity.Jobs;
using System.IO;
using Unity.Burst;
using Unity.Collections;

public class VertexAnimation : MonoBehaviour
{
    public MeshFilter filter;
    public MeshFilter meshFilter;
    public Vector3[] starVertices;
    public Vector3[] endVertices;
    [Range(0,1)]
    public float lerp;
    public bool open;
    public string[] starpoinmt ;
    public string[] endpoint;
    private JobHandle jobHandle;

    public void ReadData()
    {
        starpoinmt = File.ReadAllLines(Application.streamingAssetsPath + "/starVertices.txt");
        endpoint = File.ReadAllLines(Application.streamingAssetsPath + "/endVertices.txt");
        starVertices = new Vector3[meshFilter.mesh.vertices.Length];
        endVertices = new Vector3[meshFilter.mesh.vertices.Length];
        for (int i = 0; i < meshFilter.mesh.vertices.Length; i++)
        {
            starVertices[i] = StringToV3(starpoinmt[i]);
            endVertices[i] = StringToV3(endpoint[i]);
        }
    }
    private void Update()
    {
        if (lerp != 0 || lerp != 1)
        {
            DataJobUpdate();
        }
        #region
        //if (Input.GetKeyDown(KeyCode.S))
        //{
        //    starVertices = filter.meshFilter.vertices;
        //    string[] point = new string[starVertices.Length];
        //    for (int i = 0; i < starVertices.Length; i++)
        //    {
        //        point[i] = starVertices[i].x.ToString()+"&" + starVertices[i].y.ToString()+"&" + starVertices[i].z.ToString();
        //    }
        //    File.WriteAllLines(Application.streamingAssetsPath + "/starVertices.txt", point);
        //}


        //if (Input.GetKeyDown(KeyCode.E))
        //{
        //    endVertices = filter.meshFilter.vertices;
        //    string[] point = new string[endVertices.Length];
        //    for (int i = 0; i < endVertices.Length; i++)
        //    {
        //        point[i] = endVertices[i].x.ToString() + "&" + endVertices[i].y.ToString() + "&" + endVertices[i].z.ToString();
        //    }
        //    File.WriteAllLines(Application.streamingAssetsPath + "/endVertices.txt", point);
        //}



        // DataUpdate();

        //if (Input.GetKeyDown(KeyCode.Space)) 
        //{
        //    Debug.Log(Application.streamingAssetsPath);
        //    AssetDatabase.CreateAsset(meshFilter.meshFilter, "Assets/" + name + ".asset");
        //    AssetDatabase.SaveAssets();
        //}
        #endregion
    }



    //public void DataUpdate()
    //{
    //    if (open)
    //    {
    //        Vector3[] vertices = new Vector3[meshFilter.meshFilter.vertices.Length];
    //        for (int i = 0; i < meshFilter.meshFilter.vertices.Length; i++)
    //        {
    //            // vertices[i] = Vector3.Lerp(StringToV3(starpoinmt[i]), StringToV3(endpoint[i]), lerp);
    //            vertices[i] = Vector3.Lerp(starVertices[i], endVertices[i], lerp);
    //        }
    //        meshFilter.meshFilter.vertices = vertices;
    //        meshFilter.meshFilter.RecalculateBounds();
    //        meshFilter.meshFilter.RecalculateNormals();
    //    }
    //}

    meshFilterUpdateJobParallel jobParallel;
    NativeArray<Vector3> ver;
    NativeArray<Vector3> starVerticesNative;
    NativeArray<Vector3> endVerticesNative;
    public void DataJobUpdate() 
    {
        if (open)
        {
             ver = new NativeArray<Vector3>(meshFilter.mesh.vertices, Allocator.TempJob);
             starVerticesNative = new NativeArray<Vector3>(starVertices, Allocator.TempJob);
             endVerticesNative = new NativeArray<Vector3>(endVertices, Allocator.TempJob);

            jobParallel = new meshFilterUpdateJobParallel
            {
                vertices = ver,
                starVertices = starVerticesNative,
                endVertices = endVerticesNative,
                lerp = lerp
            };

            jobHandle = jobParallel.Schedule(ver.Length, 64);
        }
    }


    public Vector3 StringToV3(string v3s)
    {
        string[] v3p = v3s.Split("&");
        return new Vector3(float.Parse(v3p[0]),float.Parse(v3p[1]),float.Parse(v3p[2]));
    }
    void LateUpdate()
    {
        jobHandle.Complete();

        meshFilter.mesh.vertices = jobParallel.vertices.ToArray();
        meshFilter.mesh.RecalculateBounds();
        meshFilter.mesh.RecalculateNormals();

        jobParallel.vertices.Dispose();
        starVerticesNative.Dispose();
        endVerticesNative.Dispose();
    }

    [BurstCompile]
    struct meshFilterUpdateJobParallel : IJobParallelFor
    {
        public NativeArray<Vector3> vertices;
        [ReadOnly] public NativeArray<Vector3> starVertices;
        [ReadOnly] public NativeArray<Vector3> endVertices;
        [ReadOnly] public float lerp;

        public void Execute(int index)
        {
            vertices[index] = Vector3.Lerp(starVertices[index], endVertices[index], lerp);
        }
    }

}

如果各位大佬有新的思路和解决办法,欢迎留言!

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值