Unity新的MeshData API学习
在新版本的Unity中提供了MeshDataArray和MeshData等多个API,使Mesh数据操作支持多线程;以更好的支持DOTS。
API文档:https://docs.unity3d.com/es/2020.2/ScriptReference/Mesh.MeshData.html
1.IJob修改顶点
首先用Mesh.AllocateWritableMeshData分配一个可写的网格数据,然后通过jobs进行顶点操作,
最后通过Mesh.ApplyAndDisposeWritableMeshData接口赋值回Mesh。
用简单的正弦波x轴移动测试:

代码如下:
using System;
using System.Linq;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering; [RequireComponent(typeof(MeshFilter))]
public class MDT1 : MonoBehaviour
{
[BurstCompile]
public struct TestJob : IJobParallelFor
{
[ReadOnly] public float time;
[ReadOnly] public NativeArray<Vector3> sourceVertices;
[WriteOnly] public NativeArray<Vector3> writeVertices; public void Execute(int index)
{
Vector3 vert = sourceVertices[index];
vert.x += math.sin(index + time) * 0.03f;
writeVertices[index] = vert;
}
} public MeshFilter meshFilter;
private NativeArray<Vector3> mCacheVertices;
private NativeArray<Vector3> mCacheNormals; private ushort[] mCacheTriangles;
private Mesh mCacheMesh; private void Awake()
{
Mesh sourceMesh = meshFilter.sharedMesh;
mCacheVertices = new NativeArray<Vector3>(sourceMesh.vertices, Allocator.Persistent);
mCacheNormals = new NativeArray<Vector3>(sourceMesh.normals, Allocator.Persistent);
mCacheTriangles = sourceMesh.triangles
.Select(m => (ushort) m)
.ToArray(); mCacheMesh = new Mesh();
GetComponent<MeshFilter>().mesh = mCacheMesh;
} private void OnDestroy()
{
mCacheVertices.Dispose();
mCacheNormals.Dispose();
} private void Update()
{
Mesh.MeshDataArray dataArray = Mesh.AllocateWritableMeshData(1);
Mesh.MeshData data = dataArray[0]; data.SetVertexBufferParams(mCacheVertices.Length,
new VertexAttributeDescriptor(VertexAttribute.Position),
new VertexAttributeDescriptor(VertexAttribute.Normal, stream: 1));
data.SetIndexBufferParams(mCacheTriangles.Length, IndexFormat.UInt16); NativeArray<Vector3> vertices = data.GetVertexData<Vector3>();
NativeArray<ushort> indices = data.GetIndexData<ushort>(); NativeArray<Vector3> normals = new NativeArray<Vector3>(mCacheNormals.Length, Allocator.TempJob);
data.GetNormals(normals);
for (int i = 0; i < normals.Length; ++i)
normals[i] = mCacheNormals[i];
normals.Dispose(); for (int i = 0; i < mCacheTriangles.Length; ++i)
indices[i] = mCacheTriangles[i]; TestJob job = new TestJob()
{
time = Time.time,
sourceVertices = mCacheVertices,
writeVertices = vertices
}; job
.Schedule(mCacheVertices.Length, 8)
.Complete(); data.subMeshCount = 1;
data.SetSubMesh(0, new SubMeshDescriptor(0, mCacheTriangles.Length)); Mesh.ApplyAndDisposeWritableMeshData(dataArray, mCacheMesh);
mCacheMesh.RecalculateNormals();
mCacheMesh.RecalculateBounds();
}
}
2.直接通过结构获取Mesh对应字段,并修改更新
也可以设置Mesh字段结构一样的结构体,直接GetVertexData获取。这里需要注意,
要在编辑器下检查Mesh的数据,结构体需要与其保持一致。
using System;
using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering; public class MDT2 : MonoBehaviour
{
struct VertexStruct
{
public float3 pos;
public float3 normal;
public float4 tangent;
public float2 uv0;
public float2 uv1;
} public Mesh srcMesh;
public MeshFilter meshFilter; private Mesh mCacheMesh;
private NativeArray<VertexStruct> mCacheInVertices; private void Start()
{
mCacheMesh = new Mesh();
meshFilter.sharedMesh = mCacheMesh;
} private void Update()
{
Mesh.MeshDataArray inMeshDataArray = Mesh.AcquireReadOnlyMeshData(srcMesh);
Mesh.MeshData inMesh = inMeshDataArray[0];
mCacheInVertices = inMesh.GetVertexData<VertexStruct>(); int vertexCount = srcMesh.vertexCount;
int indexCount = srcMesh.triangles.Length; Mesh.MeshDataArray outMeshDataArray = Mesh.AllocateWritableMeshData(1);
Mesh.MeshData outMesh = outMeshDataArray[0];
outMesh.SetVertexBufferParams(vertexCount,
new VertexAttributeDescriptor(VertexAttribute.Position),
new VertexAttributeDescriptor(VertexAttribute.Normal),
new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, 4),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2),
new VertexAttributeDescriptor(VertexAttribute.TexCoord1, VertexAttributeFormat.Float32, 2)); outMesh.SetIndexBufferParams(indexCount, IndexFormat.UInt16); NativeArray<ushort> indices = outMesh.GetIndexData<ushort>();
for (int i = 0; i < srcMesh.triangles.Length; ++i)
indices[i] = (ushort) srcMesh.triangles[i]; NativeArray<VertexStruct> outVertices = outMesh.GetVertexData<VertexStruct>();
for (int i = 0; i < mCacheInVertices.Length; i++)
{
VertexStruct vert = mCacheInVertices[i];
vert.pos.x += math.sin(i + Time.time) * 0.03f;
outVertices[i] = vert;
} outMesh.subMeshCount = 1;
SubMeshDescriptor subMeshDesc = new SubMeshDescriptor
{
indexStart = 0,
indexCount = indexCount,
topology = MeshTopology.Triangles,
firstVertex = 0,
vertexCount = vertexCount,
bounds = new Bounds(Vector3.zero, Vector3.one * 100f)
};
outMesh.SetSubMesh(0, subMeshDesc); Mesh.ApplyAndDisposeWritableMeshData(outMeshDataArray, mCacheMesh);
mCacheMesh.RecalculateNormals();
mCacheMesh.RecalculateBounds(); mCacheInVertices.Dispose();
inMeshDataArray.Dispose();
}
}
3.Graphics Buffer
在unity2021.2版本之后可以拿到Graphics Buffer类型:
mesh.GetVertexBuffer()
该类型可直接作为Buffer参数传入ComputeShader中。具体在github上有示例:
https://github.com/Unity-Technologies/MeshApiExamples
Unity新的MeshData API学习的更多相关文章
- ASP.NET MVC Web API 学习笔记---第一个Web API程序
http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...
- NSData所有API学习
www.MyException.Cn 网友分享于:2015-04-24 浏览:0次 NSData全部API学习. 学习NSData,在网上找资料竟然都是拷贝的纯代码,没人去解释.在这种网上 ...
- 框架源码系列十一:事务管理(Spring事务管理的特点、事务概念学习、Spring事务使用学习、Spring事务管理API学习、Spring事务源码学习)
一.Spring事务管理的特点 Spring框架为事务管理提供一套统一的抽象,带来的好处有:1. 跨不同事务API的统一的编程模型,无论你使用的是jdbc.jta.jpa.hibernate.2. 支 ...
- TCP协议和socket API 学习笔记
本文转载至 http://blog.chinaunix.net/uid-16979052-id-3350958.html 分类: 原文地址:TCP协议和socket API 学习笔记 作者:gilb ...
- Servlet 常用API学习(三)
Servlet常用API学习 (三) 一.HTTPServletRequest简介 Servlet API 中定义的 ServletRequest 接口类用于封装请求消息. HttpServletRe ...
- Servlet 常用API学习(一)
Servlet常用API学习 一.Servlet体系结构(图片来自百度图片) 二.ServletConfig接口 Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外 ...
- JDBC主要API学习总结
JDBC主要API学习 一.JDBC主要API简介 JDBC API 是一系列的接口,它使得应用程序能够进行数据库联接,执行SQL语句,并且得到返回结果. 二.Driver 接口 Java.sql.D ...
- JDK1.8新特性——Stream API
JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...
- Windows API 学习
Windows API学习 以下都是我个人一些理解,笔者不太了解windows开发,如有错误请告知,非常感谢,一切以microsoft官方文档为准. https://docs.microsoft.co ...
- odoo ORM API学习总结兼orm学习教程
环境 odoo-14.0.post20221212.tar ORM API学习总结/学习教程 模型(Model) Model字段被定义为model自身的属性 from odoo import mode ...
随机推荐
- #Kruskal,可撤销并查集#CF891C Envy
题目 给出一个 \(n\) 个点 \(m\) 条边的无向图,每条边有边权,共 \(Q\) 次询问, 每次给出 \(k_i\) 条边,问这些边能否同时在一棵最小生成树上. 分析 考虑最小生成树选择的边权 ...
- #状压dp#C 计划带师
分析 状压dp显然,主要是字典序的问题, 考虑初态终态转换就可以保证字典序最小了 代码 #include <cstdio> #include <cctype> #include ...
- 使用Python插入100万条数据到MySQL数据库并将数据逐步写出到多个Excel
Python插入100万条数据到MySQL数据库 步骤一:导入所需模块和库 首先,我们需要导入 MySQL 连接器模块和 Faker 模块.MySQL 连接器模块用于连接到 MySQL 数据库,而 F ...
- Jetty的server模块
启用server模块,执行如下命令: java -jar $JETTY_HOME/start.jar --add-modules=server 命令的输出,如下: INFO : server init ...
- 直播预告丨OpenHarmony标准系统多媒体子系统之音频解读
今晚19点,OpenHarmony开源开发者成长计划知识赋能第五期"掌握OpenHarmony多媒体的框架原理"的第四节直播课,即将开播! 深开鸿资深技术专家苑春鸽老师,将在Ope ...
- SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示
SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值,分别.以下是它们的用法和示例: MIN() 函数 MIN()函数返回所选列的最小值. ...
- C#中base关键字的几种用法 (base可以对派生类(子类)实例中调用基类(父类)的构造函数方法或者基类上已经被重写的虚方法)
base最大的使用就是"面向对象"开发的多态中.base可以对派生类(子类)实例中调用基类(父类)的构造函数方法或者基类上已经被重写的虚方法. 首先声明两个类 A B public ...
- 三七互娱《斗罗大陆:魂师对决》上线,Network Kit助力玩家即刻畅玩
三七游戏旗下的年度旗舰大作<斗罗大陆:魂师对决>现已开启全平台公测.8月1日,三七互娱技术副总监出席了HMS Core.Sparkle游戏应用创新沙龙,展示了在HMS Core Netwo ...
- Qt数据结构-QString二:QString的arg能不能像Python的format一样使用
常规QString拼接字符串我们是这样写的 QString s = QString("My name is %1, age %2").arg("zhangsan" ...
- HarmonyOS Connect “Device Partner”专场FAQ来啦!
原文链接:https://mp.weixin.qq.com/s/mQJlAso293qgPlA1paxv5g,点击链接查看更多技术内容: Device Partner平台是面向AIoT产业链 ...