テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】Meshの頂点をJobSystemとBurstで操作する

Unity 2019.3からMeshの SetVertex にNativeArrayが使用できるようになったので、BurstとJobSystemでメッシュの頂点を動かしてみました。

f:id:tsubaki_t1:20191127232141g:plain

特に難しいことはしていなくて、mesh.SetVertices(Vertices); で頂点情報を注入しているだけです。他のmesh.SetNormalsmesh.SetTangents もNativeArrayが使用できるので、動的にメッシュを作って動かす系には結構ありがたいんじゃないかなと思います。

上の画像では、6*100 * 100 の頂点をNativeArrayで取得して動かしています。プロファイラで確認すると、ちゃんとBurstとJobSystemで計算できているのが確認出来ます。(諸事情合ってエディタでのプロファイルなので片手落ちではありますが)

f:id:tsubaki_t1:20191127234629j:plain

コード

using System.Collections.Generic;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using Unity.Jobs;

public class UpdateMesh : MonoBehaviour
{
    [SerializeField] Transform target;

    Mesh mesh;

    NativeArray<Vector3> Vertices;
    JobHandle handles;
    
    void Awake()
    {
        mesh = GetComponent<MeshFilter>().mesh;
    }

    void OnEnable()
    {
        // メッシュを取得
        List<Vector3> vlist = new List<Vector3>(mesh.vertexCount);
        mesh.GetVertices(vlist);
        Vertices = new NativeArray<Vector3>(vlist.ToArray(), Allocator.Persistent);
    }
    void OnDisable()
    {
        Vertices.Dispose(handles);
    }

    void Update()
    {
        handles.Complete();

        // メッシュの更新を反映
        mesh.SetVertices(Vertices);

        // メッシュを更新
        handles = new UpdateMeshJob {
            vertices = Vertices,
            position = target.position
        }.Schedule(Vertices.Length, 20);
        JobHandle.ScheduleBatchedJobs();
    }

    [Unity.Burst.BurstCompile]
    struct UpdateMeshJob : IJobParallelFor
    {
        public NativeArray<Vector3> vertices;
        public Vector3 position;

        public void Execute(int index)
        {
            var v = vertices[index];
            v.y = 0;
            v.y = math.clamp(math.distance(v, position), 0, 3) * -1.2f;
            vertices[index] = v;
        }
    }
}

感想

次はNativeSliceに対応して欲しい…(強欲)