现在的电影里有很多妖魔在死亡后身体逐渐融化并下滑最后化为一滩黑水的情景,本次出于兴趣大致研究了这个效果,原理是控制模型的顶点向一个方向坍塌,坍塌到最低点时再根据法线方向扩散形成黑水状。
第一步:
添加MeshMelt脚本,属性面板如下:
MeltDirection:融化的方向轴;
Melt Speed:融化速度;
第二步:
选择以Y轴融化为例。
首先,筛选出模型的最高点及最低点。
//获取目标网格 _Mesh = _Target.GetComponent<MeshFilter>().mesh; //获取目标所有顶点 _AllVertex = _Mesh.vertices; //记录目标融化至高点及至低点 _DissolutionMaxPoint = _DissolutionMinPoint = _AllVertex[0]; //获取目标融化至高点及至低点 for (int i = 0; i < _AllVertex.Length; i++) { if (_MeltDirection == MeltDirection.x) { if (_AllVertex[i].x < _DissolutionMinPoint.x) _DissolutionMinPoint = _AllVertex[i]; else if (_AllVertex[i].x > _DissolutionMaxPoint.x) _DissolutionMaxPoint = _AllVertex[i]; } else if (_MeltDirection == MeltDirection.y) { if (_AllVertex[i].y < _DissolutionMinPoint.y) _DissolutionMinPoint = _AllVertex[i]; else if (_AllVertex[i].y > _DissolutionMaxPoint.y) _DissolutionMaxPoint = _AllVertex[i]; } else if (_MeltDirection == MeltDirection.z) { if (_AllVertex[i].z < _DissolutionMinPoint.z) _DissolutionMinPoint = _AllVertex[i]; else if (_AllVertex[i].z > _DissolutionMaxPoint.z) _DissolutionMaxPoint = _AllVertex[i]; } } IsCanMelt = true;
然后循环遍历所有点向着最低点的高度塌陷,已达到最低点位置的点开始以法线方向扩散,当最高点低于最低点时,融化结束。
if (_MeltDirection == MeltDirection.y && _DissolutionMaxPoint.y > _DissolutionMinPoint.y) { for (int i = 0; i < _AllVertex.Length; i++) { //目标点开始塌陷 if (_AllVertex[i].y > _DissolutionMinPoint.y) { _AllVertex[i] = new Vector3(_AllVertex[i].x, _AllVertex[i].y - Time.deltaTime * _MeltSpeed, _AllVertex[i].z); } if (_AllVertex[i].y < _DissolutionMinPoint.y) { _AllVertex[i] = new Vector3(_AllVertex[i].x, _DissolutionMinPoint.y, _AllVertex[i].z); } //目标点开始扩散 if (_AllVertex[i].y == _DissolutionMinPoint.y) { _AllVertex[i] += _Mesh.normals[i] * Time.deltaTime * _MeltSpeed; } } //刷新目标网格 _Mesh.vertices = _AllVertex; _Target.GetComponent<MeshFilter>().mesh = _Mesh; //重新记录至高点 _DissolutionMaxPoint = new Vector3(_DissolutionMaxPoint.x , _DissolutionMaxPoint.y - Time.deltaTime * _MeltSpeed, _DissolutionMaxPoint.z); }
那么,核心代码主要有这两部分就完成了,之后在其他脚本里,想要动态的控制物体融化的话,可以调用融化开关函数
/// <summary> /// 开始融化 /// </summary> public void BeginMelt() { if (IsCanMelt) { IsStartMelt = true; IsCanMelt = false; transform.GetComponent<Collider>().enabled = false; } else Debug.Log("由于未知原因,目标无法融化或处于融化中!"); }
最后附上动态演示图:
-----by MeshEditor