杂篇-01-Unity中创建Mesh时遇到的问题
摘要
今天在做水渲染时,需要手动创建一个顶点数很多的Mesh让波形更加精准,写一个MeshCreater脚本,其中遇到了一些Unity限制的问题。
MeshCreater
首先了解Unity的Mesh
每一个GameObj 拥有两个组件MeshFilter和MeshRender,MeshFilter存储Mesh,MeshRender渲染Mesh
1.Mesh类
包含变量
Vector3[] vertices 顶点信息
Vector2[] uv 每个顶点对应的uv信息
int[] triangles 三角形包含的顶点的下标(构成面)
2.MeshFilter类
继承自Component,需要挂到GameObj上
包含变量
Mesh (可以是assert直接赋值,或者程序赋值)
3.MeshRender类
继承自Component,需要挂到GameObj上
自动获取Menfilter中的mesh信息,进行渲染,其中可以为各个submesh添加独立material
问题
在制作MeshCreater时,制作了个showvertex的脚本用于显示mesh的顶点,发现以下问题
每个Mesh只是一个独立的模型信息,Mesh的Vertex不会随着物体的Transform改变,需要对vertex进行Transform.transformPoint(vertex)处理后才能和游戏物体的vetex重合。
使用OnDrawGizmos 内用Gizmos绘制物体可以在Editor下进行辅助绘制,这些绘制不会再Game中出现
另一个问题,即Unity单个mesh绘制的顶点数 不能超过65535,如果超过则必须拆分绘制使用SetTriangles
在进行水渲染的时候需要大量密集的mesh顶点,超过65000很正常
拆分绘制中遇到很多问题
此时我的基本理解是,一个triangles[]中的最大和最小下标的差值不能超过65000
submesh共用vertices,使用独立的triangles,根据baseVertex对triangles中的值进行偏移
拆分成多少个submesh,每个submesh中的三角形数据如何取?
如果按照60000为一个submesh,也就是直接将mesh中前编号为0~60000的顶点作为一个triangles,编号为后面的继续分组,那么如何确定细分的这个vetices对应的triangles的大小呢?如16个顶点,2x8的顶点对应1x7=7个正方形,需7x2x3=42大小的triangle,4x4的顶点对应3x3=9个正方形,需9x2x3=54大小的triangle,这还是规则情况下,如果60000个顶点由13*1000的mesh分割开来,必定是一个多矩形和,更加复杂。舍弃该方法。
按长宽关系分割,除了某些情况如长宽大于60000,根本无法分割成整宽或者整长的mesh
分割出来的mesh只有长宽值为1无法构成正方形,根本无法构成三角形。
多个submesh之间的triangle信息缺失
这里对Unity内部的处理caculateBounds = true 之后和其为false值 究竟有什么区别?还是有疑问
上次讲到在创建均匀的正方形Mesh时,如果长宽乘积超过65535就会出现问题,所以尝试使用SubMesh来多次绘制,在取各个SubMesh的Triangles值时遇到很多问题。下面来解决
设置缓冲区格式
最简单的方法莫过于修改这个65535的限制
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32
一般默认的indexFormat设置的是16位 对应最大值就是65535 2^16-1(index是无符号的)
修改为32位后最大值变为4294967295即2^32-1
这样做对于每个mesh来说存储空间更大了,在有大量mesh时会消耗更多的资源,同时不是所有的设备平台的GPU都支持32位索引,在使用时需要慎重。
SubMesh.SetTriangles
官方文档提供的方案是使用该函数使用对超过65535索引值的顶点进行访问,具体通过参数baseVertex对索引值进行偏移
public void SetTriangles (int[] triangles, int submesh, bool calculateBounds= true, int baseVertex= 0);
现在问题是在生成width*height个顶点的矩形场景下取triangles
创建mesh流程
设置trianglesGroup[] []
遍历Mesh的每个正方形,将每个正方形的顶点索引转化为2个三角形 即6个triangles值放在trianglesGroup[GIndex] [index]下
如何控制GIndex 和 Index 使得 trianglesGroup中的所有值都在65535范围内,且可以设置对应的Vertex偏移。
尝试解决思路
一旦出现一个三角形内的两个顶点索引之差>65535则问题必无法解决,因为其需要共用同一个Vertex偏移,无论如何控制都无法保证其中两个值在0~65535范围内。所以使用该方法无法从根本上解决问题。所以最终方案不会选择该方法,下面只是为了好玩尝试在限制条件内尝试解决一下。
为了防止边界问题,可以修改为生成width*height宽高的矩形,
对应(width+1) x (height+1)个顶点,width x height 个小正方形,对应width x height x 6 个triangle
每个小正方形看做独立单元,不考虑顶点重合和不重合的情况
当索引到第index个小正方形 ,index > 65000时 切换到另一个triangles数组存储值
为了为每个triangles分配空间,需要提前计算出每个triangles数组的大小 (如果用交错数组的话)
每个正方体占用6大小的triangles
先计算出总共需要squireSize个正方形,则需要squireSize * 4 / 65000 + 1个triangles,
新的问题,实际上(x,y)的正方形其包含的四个顶点的下标最大值为y x (width+1) + x ,并不是第x个正方形的顶点最大值为(y x width + x)*4 , 所以该方法根本无法使用 :( 不过采用正方体的width和height更加便于理解,保留该设置。
在进行vertex生成时就对编号进行处理,使得每个正方形的四个角的编号相同
这样做的后果是,必须每个正方形单独分配4个顶点,否则根本无法实现(或者实现起来非常复杂)
总结
Unity中Mesh的顶点数量默认最大值为65535,如果超过会出现问题,可以通过以下代码修改限制为2^32-1
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32
在外部导入模型的时候,可使用submesh,在外部的Maya,Max等建模的时候设置好顶点范围
如帽子,衣服,裤子,头部等等分成独立的submesh,使得每个个体顶点数在限制范围内
submesh也以采用不同的材质,可以做出某些效果。
思考
引擎的限制,会导致其对美术资源有一定的限制,所以对美术资源的把关非常重要,有时候会为了效果去研究修改引擎底层的限制,有时候为了表现的性能,平台的兼容,研究开发能力的限制,导致不得不牺牲效果。需要在技术和美术之间的权衡,这是一件非常需要经验的事情,只能慢慢向前走了。
杂篇-01-Unity中创建Mesh时遇到的问题相关推荐
- 学习在Unity中创建一个动作RPG游戏
游戏开发变得简单.使用Unity学习C#并创建您自己的动作角色扮演游戏! 你会学到什么 学习C#,一种现代通用的编程语言. 了解Unity中2D发展的能力. 发展强大的和可移植的解决问题的技能. 了解 ...
- 学习用C#在Unity中创建一个2D Metroidvania游戏
学习用C#在Unity中创建一个2D Metroidvania游戏 你会学到: 构建2D Unity游戏 用C#编程 玩家统计,水平提升,米尔和远程攻击 敌方人工智能系统 制定级别和级别选择 Lear ...
- 学会在Unity中创建一个Match-3益智游戏 Learn To Create a Match-3 Puzzle Game in Unity
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:48场讲座(6h 38m) |大小解压后:2.8 G ...
- Unity中创建本地多人游戏完整案例视频教程 Learn To Create A Local Multiplayer Game In Unity
Unity中创建本地多人游戏完整案例视频教程 Learn To Create A Local Multiplayer Game In Unity MP4 |视频:h264,1280x720 |音频:A ...
- 在Unity中创建基于Node节点的编辑器 (二) 窗口序列化
孙广东 2018.5.13 csdn 的产品 , 真垃圾, 不想吐槽了, 文章保存就丢! 没办法 . 怎么不满意, 还是得继续用, 哎~~~ 第二部分 在Unity中序列化基于节点的 ...
- 在Unity中创建基于Node节点的编辑器 (一)
孙广东 2018.5.13 Unity AssetStore中关于Node节点 编辑器相关的插件可是数不胜数, 状态机,行为树,Shader 可视化等等. Unity自己也有 Animator的 ...
- Windows下在Django中创建项目时ImportError: No module named django.core解决方法
Windows下在Django中创建项目时ImportError: No module named django.core解决方法 今天在对照<Python编程:从入门到实践>学## 标题 ...
- unity中创建游戏场景_在Unity中创建Beat Em Up游戏
unity中创建游戏场景 Learn how to use Unity to create a 3D Beat Em Up game in this full tutorial from Awesom ...
- oracle杀死进程时权限不足_在oracle中创建函数时权限不足
我对oracle有一点了解.我试图创建一个如下所示的函数.在oracle中创建函数时权限不足 CREATE OR REPLACE FUNCTION "BOOK"."CON ...
最新文章
- Java培训零基础学员必须要知道的知识点
- 三代测序的基本原理、组装方法和应用场景
- 用XFTP向Linux上传文件时出现Permission is not allowed
- php fsockopen socket,PHP利用socket(fsockopen)的简单示例
- Pytorch(二) --梯度下降法
- 探测与响应是各企业机构在2017年的首要安全事务
- Java笔记-使用ServerSocket构建HTTP服务器
- Javascript设计模式与开发实践读书笔记(1-3章)
- error in static/js/xxx.js from UglifyJs Unpected token: punc() [static/js/xxx.js]
- Ubuntu8.04系列二-系统优化篇
- java textarea append_JavaFX TextArea.append()导致java.lang.NullPointerException
- 今天带你详细了解各组件原理
- Vuejs --01 起步
- IT前景---网络工程师规划之路
- android技术服务,Android Service学习之本地服务
- 《Android进阶解密》— Android 书籍
- mysql postgresql nav_Mysql/postgreSQL
- C/C++[codeup 1978]排序
- 搭建公司wiki系统
- 如何编辑修改PDF文件内容?修改方法很简单