网上的unity破碎插件很多,不过想着可以以自己的方式实现也不失为一种乐趣,虽然整体的表现性上显得有些差,但也并不会影响最终的效果,接下来我大致讲解一下破碎一个物体的流程,因为用到了协程计算碎片的原因,所以会在所有碎片计算完成以后才会触发碎片的物理效果,所以有些模型可能会显得卡顿一下。

第一步:


添加MeshBroken脚本,目前破碎参数还较少,可以进行一些适当的调节以达到不同的破碎效果,不过建议面数过多的物体慎用,因为这里破碎的碎块数量必须大于等于原网格的面数(至于为什么呢,那是因为我目前还没想到可以数目随机、位置随机的组合多个三角面的方式,如果有相关思路的欢迎一起讨论)。

IsBrokenOnHit:物体受到碰撞时自动破碎,无论是实际碰撞还是触发器碰撞;

FragmentNum:碎片数量;

SurfaceFragmentThickness:面片破碎时单个面片厚度;

GridFragmentMinThickness:块状破碎时单个碎块厚度变化最小值;

GridFragmentMaxThickness:块状破碎时单个碎块厚度变化最大值;

FragmentStyle:碎片类型,可选择surface(面片破碎),grid(块状破碎);

BrokenStyle:破碎方式,可选择statice(静态破碎),explode(爆炸破碎);

ExplosiveForce:爆炸破碎时的爆炸力;

ExplosionRange:爆炸破碎时的爆炸力作用范围;

第二步:


效果演示。

第三步:


实现的大致流程。

首先,开始破碎时,我们先要计算所有的碎片组成(所以比较耗性能,破碎过程是即时计算的),因为目前的破碎方式是按模型原本面数进行计算的,如果模型的面数小于碎片需求,则需要按一定的规则破开部分面

/// <summary>/// 计算所有碎片/// </summary>List<List<List<int>>> ComputeAllFragment(){List<List<List<int>>> allFragment = new List<List<List<int>>>();//碎片数量大于面数,则破开一定的面if (_FragmentNum > _AllTriangleList.Count){int num = _FragmentNum - _AllTriangleList.Count;while (num > 0){CutApartSurface(_AllTriangleList[Random.Range(0, _AllTriangleList.Count)]);num -= 1;}}//按模型面数进行破碎for (int i = 0; i < _AllTriangleList.Count; i++){List<List<int>> fragment = new List<List<int>>();fragment.Add(_AllTriangleList[i]);allFragment.Add(fragment);}return allFragment;}

破开一个面的方式

/// <summary>/// 将一个面割开/// </summary>/// <param name="triangle">面片</param>void CutApartSurface(List<int> triangle){Vector3 vertices0 = _AllVerticesList[triangle[0]];Vector3 vertices1 = _AllVerticesList[triangle[1]];Vector3 vertices2 = _AllVerticesList[triangle[2]];//计算新顶点坐标Vector3 newVertex = new Vector3((vertices1.x - vertices2.x) / 2.0f + vertices2.x,(vertices1.y - vertices2.y) / 2.0f + vertices2.y,(vertices1.z - vertices2.z) / 2.0f + vertices2.z);//计算新顶点的UVVector2[] uv = _Uv;Vector2[] Newuv = new Vector2[uv.Length + 1];for (int i = 0; i < uv.Length; i++){Newuv[i] = uv[i];}Newuv[Newuv.Length - 1] = new Vector2((uv[triangle[1]].x - uv[triangle[2]].x) / 2 + uv[triangle[2]].x, (uv[triangle[1]].y - uv[triangle[2]].y) / 2 + uv[triangle[2]].y);_Uv = Newuv;//计算新顶点的法线Vector3[] normal = _Normal;Vector3[] Newnormal = new Vector3[normal.Length + 1];for (int i = 0; i < normal.Length; i++){Newnormal[i] = normal[i];}Newnormal[Newnormal.Length - 1] = _Normal[triangle[2]];_Normal = Newnormal;//新顶点加入所有顶点集合_AllVerticesList.Add(newVertex);//记录新顶点索引int _index = _AllVerticesList.IndexOf(newVertex);//割开三角面List<int> newTriangle1 = new List<int>();List<int> newTriangle2 = new List<int>();newTriangle1.Add(triangle[0]);newTriangle1.Add(triangle[1]);newTriangle1.Add(_index);newTriangle2.Add(_index);newTriangle2.Add(triangle[2]);newTriangle2.Add(triangle[0]);_AllTriangleList.Remove(triangle);_AllTriangleList.Add(newTriangle1);_AllTriangleList.Add(newTriangle2);}

所有的碎片组成方式都计算完毕之后,便保存所有碎片集合,遍历集合以生成所有碎片

/// <summary>/// 生成网格碎片/// </summary>void ProduceGridFragment(List<List<int>> fragment){//新建碎片物体GameObject obj = new GameObject(transform.name + "_fragment" + transform.childCount);obj.transform.position = transform.position;obj.transform.rotation = transform.rotation;obj.transform.localScale = transform.localScale;obj.transform.SetParent(transform);obj.AddComponent<MeshFilter>();obj.AddComponent<MeshRenderer>();obj.GetComponent<MeshRenderer>().material = GetComponent<MeshRenderer>().material;Mesh _mesh = new Mesh();_mesh.Clear();//不合法的碎片if (fragment.Count < 1 || fragment[0].Count < 3)return;//计算碎片的顶点Vector3[] _fragment = new Vector3[] {_AllVerticesList[fragment[0][0]],_AllVerticesList[fragment[0][1]],_AllVerticesList[fragment[0][2]],_AllVerticesList[fragment[0][2]] - _Normal[fragment[0][2]] * Random.Range(_GridFragmentMinThickness,_GridFragmentMaxThickness),_AllVerticesList[fragment[0][1]] - _Normal[fragment[0][2]] * Random.Range(_GridFragmentMinThickness,_GridFragmentMaxThickness),_AllVerticesList[fragment[0][0]] - _Normal[fragment[0][2]] * Random.Range(_GridFragmentMinThickness,_GridFragmentMaxThickness)};//计算碎片的三角面int[] _triangle = new int[] {0,1,2,3,4,5,2,1,4,4,3,2,0,2,3,0,3,5,5,4,1,5,1,0};//计算碎片的uvVector2[] _uv = new Vector2[] {_Uv[fragment[0][0]],_Uv[fragment[0][1]],_Uv[fragment[0][2]],_Uv[fragment[0][2]],_Uv[fragment[0][1]],_Uv[fragment[0][0]]};_mesh.vertices = _fragment;_mesh.triangles = _triangle;_mesh.uv = _uv;//生成碎片_mesh.name = transform.name + "_fragment" + transform.childCount;_mesh.RecalculateNormals();obj.GetComponent<MeshFilter>().mesh = _mesh;_Fragment.Add(obj);}

之后在其他脚本里,想要动态的控制物体的破碎的话,可以在外部调用破碎开关函数

/// <summary>/// 开始破碎/// </summary>public void BeginBroken(){if (IsCanBroken){StartCoroutine(BroKening());IsCanBroken = false;}elseDebug.Log("由于未知原因,目标无法破碎!");}

最后附上动态演示图:

-----by MeshEditor

Unity插件 - MeshEditor(三) 面片破碎网格破碎相关推荐

  1. Unity插件 - MeshEditor(十) 模型风力拉扯特效

    更新日期:2020年4月23日.  Github源码:[点我获取源码] 先上几张效果图: (导演:我们需要一个刮风的效果,道具组,上大风扇) (导演:咔!!!行了,道具组你们明天不用来上班了) (大风 ...

  2. unityar自动识别人脸_三款Unity插件带您玩转人脸识别与模拟

    原标题:三款Unity插件带您玩转人脸识别与模拟 若想让游戏或电影中的虚拟角色表现得更加真实,面部表情是至关重要的.人脸识别技术则借助真人表演来为虚拟角色赋予丰富的表情与面部动作,小至皱眉带动眼部肌肉 ...

  3. 【Unity插件】最多的插件合集

    一.前言 ? 最近整理了一下文章,发现我分享了很多的插件,但是如果要查找某一款插件,还需要去搜索才能找到,很不方面,就想要将写过的所有的插件分享也好,教程也好,做一个汇总,然后这篇文章还会不断的更新, ...

  4. ugui 转轮_【Unity插件】FingerGestures 插件使用

    FingerGesture在项目中的作用是管理用户输入和识别手势和鼠标或手指事件.可能有些人还不是很会用,下面就给大家介绍下Unity插件FingerGesture的使用教程. fingerGestu ...

  5. Unity插件:UFPS

    Unity插件:UFPS使用教程(一) Unity插件:UFPS使用教程(一) Unity插件:UFPS使用教程(一) 先挂上UFPS官方文档:https://docs.google.com/docu ...

  6. Asset Store上常用的40个Unity插件汇总——进阶开发者必备Unity插件

    上篇文章着重介绍了Unity Asset Store(Unity资源商店)上一些超棒的资源与素材. unity老司机的资源推荐与常用插件汇总合集 - 简书 Unity插件资源购买小技巧 - 简书 本篇 ...

  7. 相见恨晚!Unity插件——DoTween介绍

    前言: 今天来学习一下大名鼎鼎的Unity插件--DoTween. DoTween DOTween是一款针对Unity的快速高效.类型安全的面向对象的补间动画引擎,并且对于C#用户做出了很多的优化. ...

  8. Unity插件:Unity使用spine动画

    一.spine动画介绍 动画能给游戏带来生机和灵气.我们相信创作一段美妙的动画,不仅需要强大的软件工具,更需要一套牛 B 的工作流程.Spine 专注于此,为您创建惊艳的骨骼动画,并将其整合到游戏当中 ...

  9. Unity插件NativeGallery拉取手机相册的使用简记

    Unity插件NativeGallery拉取手机相册的使用简记 拉取手机相册 文档摘要 1. 关于 2. 使用设置 3.常见问题解答 项目示例 资源链接 拉取手机相册 项目中使用到了拉取手机相册的功能 ...

最新文章

  1. boost::locale::to_upper用法的测试程序
  2. 速查100 WebServers
  3. WAP2.0开发规范及原则
  4. 数据积分-牛顿科茨法与高斯勒让德法对比及示例
  5. 双十一终极预告:免单+半价+100% 中奖,没有套路,直降直减!
  6. flash as3鼠标左右拖动元件
  7. 8086cpu学习笔记(3):寻址方式
  8. [每日一氵] mmSeg 报错 StopIteration
  9. java安装后为什么是英文_java用到英语多吗
  10. 如何搭建易企秀H5平台?
  11. python中turtle画雪花_turtle画雪花-方法及效果的详解
  12. 9.1 数据库事务概述
  13. Java程序为身份证照片添加马赛克
  14. Swift5.1 语言指南(十三) 方法
  15. ITK——5. 利用ITK自身的多线程加速filter计算
  16. c语言鼠标打地鼠程序,如何使用C语言实现打地鼠的游戏
  17. ESP32超详细学习记录:NTP同步时间
  18. opencv2 读取16bit图像数据小结
  19. 梦想成真---jdk版本的选择(推荐1.8)
  20. 【微信小程序入门到精通】—小程序实战构建售货平台首页

热门文章

  1. 兰州大学中外合资计算机专业怎么样,兰州大学与美国德雷塞尔大学拟合作举办计算机科学与技术专业(数据科学方向)本科教育项目...
  2. 什么是区块链共识算法?
  3. jetson nano 烧录、更换镜像源、配置xrdp、安装Archiconda、配置CUDA、安装pytorch环境一条龙服务
  4. Java 17 新特性尝鲜
  5. CSMA/CA协议详解【计算机网络】
  6. GDD无监督图像对融合 论文笔记
  7. Eclipse笔记-Build path entry is missing: org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.inter
  8. win10系统设置虚拟化-Inter Virtualization Technology
  9. meta http-equiv=refresh content=300 什么意思?
  10. js 实现经典阶乘函数的计算