优化Unity3D插件Ezy-Slice部分缺陷

文章介绍了在Unity3D中开发类似《水果忍者》游戏时,如何利用Ezy-Slice插件进行Mesh切割优化。作者指出原插件在处理共线线段时的不足,并提出改进方案,通过有向连通图算法处理凹字型结构,以生成更精确的侧面Mesh。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 Unity3D中,如果制作者想开发一款类似《水果忍者》类型的游戏,需要利用到Mesh的切割技术,那我认为Ezy-Slice这款插件是必不可少的。本文着重讲解的是如何优化,代码的细节部分我不会过多讲解。有需要的可以自行去官网下载理解。

作者也是第一次写这类技术文章,作为刚入职工作的比较满意的成果,如果有地方写的不好请大家谅解~

插件网址GitHub - DavidArayan/ezy-slice: An open source mesh slicer framework for Unity3D Game Engine. Written in C#.

首先该插件使用的主要方法入口是SliceObject,需要提供一个被切割的物体GameObject,一个起始的坐标和法线方向,法线方向就是切割完法线朝着的那一侧为正侧,另一侧为反侧。

public SlicedHull SliceObject(GameObject obj, Vector3 StartPosition, Vector3 Normal, Material crossSectionMaterial = null)
    {
        // slice the provided object using the transforms of this object
        return obj.Slice(StartPosition, Normal, crossSectionMaterial);
    }

在Slicer类中有这么一个方法

public static SlicedHull Slice(Mesh sharedMesh, Plane pl, TextureRegion region, int crossIndex)

此处将所有的Mesh分为一个个三角面,让每个三角面和入口传入的这个‘片’进行判断是否在正面、侧面、还是相交。相对的,如果两个面有相交,则需要把交点求出。

此处就代码可以进行优化,在制作过程中,原作者并没有把刚刚好共线的线添加到相交的类型里面,导致如果我们切割的时候恰好是沿着这个模型某一条线段进行切割,就会导致缺少这个刚刚好平行的线段,也就是少点了,就无法补足侧面,所以我做了一下的更新。这样就可以把刚刚好是在平面上或者是相交的线段加入到所有相交的点数组中。

                    if (side == SideOfPlane.UP || side == SideOfPlane.ON)
                        {
                            mesh.upperHull.Add(newTri);

                            if (sa == SideOfPlane.ON && sa == sb)
                            //如果刚刚好在平面上,直接将线段当作交点加进去
                            {
                                result.AddIntersectionPoint(verts[i0]);
                                result.AddIntersectionPoint(verts[i1]);
                            }
                            else if (sa == SideOfPlane.ON && sa == sc)
                            {
                                result.AddIntersectionPoint(verts[i0]);
                                result.AddIntersectionPoint(verts[i2]);
                            }
                            else if (sb == SideOfPlane.ON && sb == sc)
                            {
                                result.AddIntersectionPoint(verts[i1]);
                                result.AddIntersectionPoint(verts[i2]);
                            }
                            int interHullCount = result.intersectionPointCount;
                            for (int i = 0; i < interHullCount; i++)
                            {
                                var n = result.intersectionPoints[i];
                                n.i = index + startIndex;
                                crossHull.Add(n);
                            }
                        }

好了,此处我们将所有相交的点已经加入,但是在Triangulator这个类中。原作者使用的是凸包算法,也就是在空间的游离点中,寻找所有最外围的点,把他们围成新的Mesh。但是如果我们的模型是具有凹字型结构,就无法适用这套算法,所以我们采用的是有向连通图的算法,通过线段和线段,最近点和点进行合并的算法。达成连接一个空间中游离点的最大环

while (testmapped.Count > 1)
            {
                Mapped2D mpnext = testmapped.Find(m => m.index == currentmp.index);
                newmapped.Add(mpnext);
                testmapped.Remove(mpnext);
                float minDistance = float.MaxValue;
                Mapped2D mpnear = testmapped[0];
                testmapped.ForEach(m =>
                {
                    float distance = Vector2.Distance(m.mappedValue, mpnext.mappedValue);
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                        mpnear = m;
                    }
                });
                testmapped.Remove(mpnear);
                currentmp = mpnear;
            }

这些点就自然而然的连起来了,再用上平面三角面的构造函数,构造出来侧面的Mesh,这样就大功告成了!

这是结果

 以后我还会分享一些在工作中遇到的困难和解决思路~希望各位大佬海涵

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值