Unity【Bounds & Vector3 Cross】- 如何判断一个物体是否在一个凸边体三维区域内

简介: Unity【Bounds & Vector3 Cross】- 如何判断一个物体是否在一个凸边体三维区域内

image.gif

如图所示,本文介绍如何判断一个物体是否被一个凸边体区域所囊括,本文将该功能的实现拆分成了如下步骤:

1.如何判断两条线段是否相交

2.如何判断一个点是否在一个凸边形范围内(2D、xz轴构成的平面)

3.如何判断一个点是否在一个凸边体范围内(3D)

4.如何判断一个物体是否在一个凸边体范围内

依次实现:

1.如何判断两条线段是否相交:

通过矢量叉积的符号可以判断两矢量相互之间的顺逆时针关系,如下图所示,点A和点B分别在线段CD两侧,点C和点D分别在线段AB两侧,这时可以判断它们相交。判断点A和点B是否在线段CD两侧,也就是判断向量A-D和向量B-D在向量C-D的两侧,也就是叉积的结果是异号的,即:(A-D)X(C-D)*(B-D)X(C-D)< 0。同样的,判断点C和点B是否在线段AB的两侧:(D-A)X(B-A)*(C-A)X(B-A)< 0,以上这两个条件成立时,可判断两线段相交。

image.gif

当然,出现以下这种情况,即(A-D)X(C-D)*(B-D)X(C-D)= 0时,两条线段也是相交的:

image.gif

在Unity中封装该判断函数:

//判断AB与CD是否相交privateboolIsIntersection(Vector3A, Vector3B, Vector3C, Vector3D)
{
//A-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign1=Mathf.Sign(Vector3.Cross(A-D, C-D).y);
//B-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign2=Mathf.Sign(Vector3.Cross(B-D, C-D).y);
//C-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign3=Mathf.Sign(Vector3.Cross(C-A, B-A).y);
//D-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign4=Mathf.Sign(Vector3.Cross(D-A, B-A).y);
//AB与CD相交返回true 否则返回falsereturn!Mathf.Approximately(sign1, sign2) &&!Mathf.Approximately(sign3, sign4);
}

image.gif

image.gif

测试脚本如下:

usingUnityEngine;
usingUnityEditor;
publicclassExample : MonoBehaviour{
    [SerializeField] privateTransforma;
    [SerializeField] privateTransformb;
    [SerializeField] privateTransformc;
    [SerializeField] privateTransformd;
//判断AB与CD是否相交privateboolIsIntersection(Vector3A, Vector3B, Vector3C, Vector3D)
    {
//A-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign1=Mathf.Sign(Vector3.Cross(A-D, C-D).y);
//B-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign2=Mathf.Sign(Vector3.Cross(B-D, C-D).y);
//C-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign3=Mathf.Sign(Vector3.Cross(C-A, B-A).y);
//D-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign4=Mathf.Sign(Vector3.Cross(D-A, B-A).y);
//AB与CD相交返回true 否则返回falsereturn!Mathf.Approximately(sign1, sign2) &&!Mathf.Approximately(sign3, sign4);
    }
privatevoidOnDrawGizmos()
    {
if (a==null||b==null||c==null||d==null) return;
Handles.Label(a.position, "A");
Handles.Label(b.position, "B");
Handles.Label(c.position, "C");
Handles.Label(d.position, "D");
boolflag=IsIntersection(a.position, b.position, c.position, d.position);
Handles.color=flag?Color.cyan : Color.red;
Handles.DrawLine(a.position, b.position);
Handles.DrawLine(c.position, d.position);
    }
}

image.gif

2.如何判断一个点是否在一个凸边形范围内(2D、xz轴构成的平面):

若从该点发出的射线与平面内凸边形的交点的个数为偶数,则点在凸边形外,若为奇数,则点在凸边形内。因此取一条从该点向凸边形发出的射线,遍历凸边形的每一条边,判断射线与边的交点个数,若个数为奇数,则可以判断该点在凸边形范围内。

//判断点A是否在凸边型范围内privateboolIsInRange(Transform[] points, Vector3A)
{
//取第一条边中点Vector3half01= (points[0].position+points[1].position) * .5f;
//中点延伸(射线)half01+= (half01-A).normalized*100000;
//用于记录交点的个数intcount=0;
//遍历for (inti=0; i<points.Length; i++)
    {
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
//判断是否相交if (IsIntersection(a.position, b.position, A, half01)) count++;
    }
//交点个数为奇数则表示点A在凸边型范围内returncount%2==1;
}

image.gif

image.gif

测试代码如下:

usingUnityEngine;
usingUnityEditor;
publicclassExample : MonoBehaviour{
    [SerializeField] privateTransformpoint;
    [SerializeField] privateTransform[] points; //凸边型顶点集合//判断点A是否在凸边型范围内privateboolIsInRange(Transform[] points, Vector3A)
    {
//取第一条边中点Vector3half01= (points[0].position+points[1].position) * .5f;
//中点延伸(射线)half01+= (half01-A).normalized*100000;
//用于记录交点的个数intcount=0;
//遍历for (inti=0; i<points.Length; i++)
        {
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
//判断是否相交if (IsIntersection(a.position, b.position, A, half01)) count++;
        }
//交点个数为奇数则表示点A在凸边型范围内returncount%2==1;
    }
//判断AB与CD是否相交privateboolIsIntersection(Vector3A, Vector3B, Vector3C, Vector3D)
    {
//A-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign1=Mathf.Sign(Vector3.Cross(A-D, C-D).y);
//B-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign2=Mathf.Sign(Vector3.Cross(B-D, C-D).y);
//C-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign3=Mathf.Sign(Vector3.Cross(C-A, B-A).y);
//D-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign4=Mathf.Sign(Vector3.Cross(D-A, B-A).y);
//AB与CD相交返回true 否则返回falsereturn!Mathf.Approximately(sign1, sign2) &&!Mathf.Approximately(sign3, sign4);
    }
privatevoidOnDrawGizmos()
    {
if (points.Length<3||point==null) return;
boolflag=IsInRange(points, point.position);
Handles.Label(point.position, "A");
Vector3half01= (points[0].position+points[1].position) * .5f;
half01+= (half01-point.position).normalized*100000;
for (inti=0; i<points.Length; i++)
        {
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
Handles.color=flag?Color.cyan : Color.red;
Handles.DrawLine(a.position, b.position);
Handles.Label(points[i].position, $"顶点{i + 1}");
Handles.color=Color.yellow;
if (IsIntersection(a.position, b.position, point.position, half01))
            {
Handles.DrawLine(point.position, half01);
            }
        }
    }
}

image.gif

3.如何判断一个点是否在一个凸边体范围内(3D):

上述部分我们在xz轴所在的平面构建了一个凸边形,现在我们给其一个高度,即可构成一个凸边体空间区域:

image.gif

要判断一个点是否在该凸边体范围内,只需要在满足处于xz轴所在的凸边形范围内的同时,其坐标点的y值既小等于凸边体height高度值的一半,又大等于负的高度值的一半:

image.gif

封装判断函数:

//判断点A是否在凸边体范围内privateboolIsInRange(Transform[] points, floatheight, Vector3A)
{
boolflag=true;
flag&=A.y<=height* .5f;
flag&=A.y>=-height* .5f;
flag&=IsInRange(points, A);
returnflag;
}

image.gif

image.gif

测试代码如下:

usingUnityEngine;
usingUnityEditor;
publicclassExample : MonoBehaviour{
    [SerializeField] privateTransformpoint;
    [SerializeField] privateTransform[] points; //凸边型顶点集合    [SerializeField] privatefloatheight=1f;
//判断点A是否在凸边体范围内privateboolIsInRange(Transform[] points, floatheight, Vector3A)
    {
boolflag=true;
flag&=A.y<=height* .5f;
flag&=A.y>=-height* .5f;
flag&=IsInRange(points, A);
returnflag;
    }
//判断点A是否在凸边型范围内privateboolIsInRange(Transform[] points, Vector3A)
    {
//取第一条边中点Vector3half01= (points[0].position+points[1].position) * .5f;
//中点延伸(射线)half01+= (half01-A).normalized*100000;
//用于记录交点的个数intcount=0;
//遍历for (inti=0; i<points.Length; i++)
        {
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
//判断是否相交if (IsIntersection(a.position, b.position, A, half01)) count++;
        }
//交点个数为奇数则表示点A在凸边型范围内returncount%2==1;
    }
//判断AB与CD是否相交privateboolIsIntersection(Vector3A, Vector3B, Vector3C, Vector3D)
    {
//A-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign1=Mathf.Sign(Vector3.Cross(A-D, C-D).y);
//B-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign2=Mathf.Sign(Vector3.Cross(B-D, C-D).y);
//C-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign3=Mathf.Sign(Vector3.Cross(C-A, B-A).y);
//D-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign4=Mathf.Sign(Vector3.Cross(D-A, B-A).y);
//AB与CD相交返回true 否则返回falsereturn!Mathf.Approximately(sign1, sign2) &&!Mathf.Approximately(sign3, sign4);
    }
privatevoidOnDrawGizmos()
    {
if (points.Length<3||point==null) return;
boolflag=IsInRange(points, height, point.position);
Handles.color=flag?Color.cyan : Color.red;
Handles.Label(point.position, "A");
for (inti=0; i<points.Length; i++)
        {
Handles.Label(points[i].position-newVector3(0, height* .5f, 0), $"顶点{i + 1}");
Handles.Label(points[i].position+newVector3(0, height* .5f, 0), $"顶点{i + 1 + points.Length}");
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
varminA=a.position-newVector3(0, height* .5f, 0);
varmaxA=a.position+newVector3(0, height* .5f, 0);
varminB=b.position-newVector3(0, height* .5f, 0);
varmaxB=b.position+newVector3(0, height* .5f, 0);
Handles.DrawAAPolyLine(minA, minB);
Handles.DrawAAPolyLine(maxA, maxB);
Handles.DrawAAPolyLine(minA, maxA);
Handles.DrawAAPolyLine(minB, maxB);
        }
    }
}

image.gif

4.如何判断一个物体是否在一个凸边体范围内:

上述部分判断的是一个坐标点是否在一个凸边体范围内,要判断一个物体是否被该凸边体区域所囊括,需要获取该物体及其子物体构成的Bounds边界盒,如果Bounds边界盒的每一个顶点都在该凸边体范围内,则可以大致推断该物体被这个凸边体所囊括,当然要想更精确还是要获取该物体的更为精确的边界点,在这里不做延申。

首先来看Unity圣典中关于Bounds边界盒及其核心变量的介绍:

image.gif

其中max、min分别是最大、最小点,可以通过这两点获取到其它各顶点的坐标,测试代码如下:

usingUnityEngine;
usingUnityEditor;
publicclassExample : MonoBehaviour{
    [SerializeField] privateGameObjectobj;
privatevoidOnDrawGizmos()
    {
if (obj==null) return;
Boundsbounds=obj.GetComponent<MeshRenderer>().bounds;
Vector3point1=bounds.min;
Vector3point2=bounds.max;
Vector3point3=newVector3(point1.x, point1.y, point2.z);
Vector3point4=newVector3(point1.x, point2.y, point1.z);
Vector3point5=newVector3(point2.x, point1.y, point1.z);
Vector3point6=newVector3(point1.x, point2.y, point2.z);
Vector3point7=newVector3(point2.x, point1.y, point2.z);
Vector3point8=newVector3(point2.x, point2.y, point1.z);
Handles.DrawLine(point6, point2);
Handles.DrawLine(point2, point8);
Handles.DrawLine(point8, point4);
Handles.DrawLine(point4, point6);
Handles.DrawLine(point3, point7);
Handles.DrawLine(point7, point5);
Handles.DrawLine(point5, point1);
Handles.DrawLine(point1, point3);
Handles.DrawLine(point6, point3);
Handles.DrawLine(point2, point7);
Handles.DrawLine(point8, point5);
Handles.DrawLine(point4, point1);
Handles.Label(point1, "顶点1");
Handles.Label(point2, "顶点2");
Handles.Label(point3, "顶点3");
Handles.Label(point4, "顶点4");
Handles.Label(point5, "顶点5");
Handles.Label(point6, "顶点6");
Handles.Label(point7, "顶点7");
Handles.Label(point8, "顶点8");
    }
}

image.gif

image.gif

一个物体可能包含若干个带有MeshRenderer组件的子物体,因此我们要获取一个囊括所有的Bounds边界盒,要使用到Bounds类中的Encapsulate函数:

usingUnityEngine;
usingUnityEditor;
publicclassExample : MonoBehaviour{
    [SerializeField] privateGameObjectobj;
privatevoidOnDrawGizmos()
    {
if (obj==null) return;
Boundsbounds=newBounds(Vector3.zero, Vector3.zero);
//获取所有MeshRenderer 包括子物体varmrs=obj.GetComponentsInChildren<MeshRenderer>(true);
Vector3center=Vector3.zero;
for (inti=0; i<mrs.Length; i++)
        {
center+=mrs[i].bounds.center;
//Encapsulate函数重新计算boundsbounds.Encapsulate(mrs[i].bounds);
        }
Vector3point1=bounds.min;
Vector3point2=bounds.max;
Vector3point3=newVector3(point1.x, point1.y, point2.z);
Vector3point4=newVector3(point1.x, point2.y, point1.z);
Vector3point5=newVector3(point2.x, point1.y, point1.z);
Vector3point6=newVector3(point1.x, point2.y, point2.z);
Vector3point7=newVector3(point2.x, point1.y, point2.z);
Vector3point8=newVector3(point2.x, point2.y, point1.z);
Handles.DrawLine(point6, point2);
Handles.DrawLine(point2, point8);
Handles.DrawLine(point8, point4);
Handles.DrawLine(point4, point6);
Handles.DrawLine(point3, point7);
Handles.DrawLine(point7, point5);
Handles.DrawLine(point5, point1);
Handles.DrawLine(point1, point3);
Handles.DrawLine(point6, point3);
Handles.DrawLine(point2, point7);
Handles.DrawLine(point8, point5);
Handles.DrawLine(point4, point1);
Handles.Label(point1, "顶点1");
Handles.Label(point2, "顶点2");
Handles.Label(point3, "顶点3");
Handles.Label(point4, "顶点4");
Handles.Label(point5, "顶点5");
Handles.Label(point6, "顶点6");
Handles.Label(point7, "顶点7");
Handles.Label(point8, "顶点8");
    }
}

image.gif

image.gif

封装判断函数:

//判断一个物体是否在凸边体范围内privateboolIsInRange(Transform[] points, floatheight, GameObjectobj)
{
Boundsbounds=newBounds(Vector3.zero, Vector3.zero);
//获取所有MeshRenderer 包括子物体varmrs=obj.GetComponentsInChildren<MeshRenderer>(true);
Vector3center=Vector3.zero;
for (inti=0; i<mrs.Length; i++)
    {
center+=mrs[i].bounds.center;
//Encapsulate函数重新计算boundsbounds.Encapsulate(mrs[i].bounds);
    }
Vector3min=bounds.min;
Vector3max=bounds.max;
returnIsInRange(points, height, min)
&&IsInRange(points, height, max)
&&IsInRange(points, height, newVector3(min.x, min.y, max.z))
&&IsInRange(points, height, newVector3(min.x, max.y, min.z))
&&IsInRange(points, height, newVector3(max.x, min.y, min.z))
&&IsInRange(points, height, newVector3(min.x, max.y, max.z))
&&IsInRange(points, height, newVector3(max.x, min.y, max.z))
&&IsInRange(points, height, newVector3(max.x, max.y, min.z));
}

image.gif

image.gif

测试代码如下:

usingUnityEngine;
usingUnityEditor;
publicclassExample : MonoBehaviour{
    [SerializeField] privateGameObjectobj;
    [SerializeField] privateTransform[] points; //凸边型顶点集合    [SerializeField] privatefloatheight=1f;
//判断一个物体是否在凸边体范围内privateboolIsInRange(Transform[] points, floatheight, GameObjectobj)
    {
Boundsbounds=newBounds(Vector3.zero, Vector3.zero);
//获取所有MeshRenderer 包括子物体varmrs=obj.GetComponentsInChildren<MeshRenderer>(true);
Vector3center=Vector3.zero;
for (inti=0; i<mrs.Length; i++)
        {
center+=mrs[i].bounds.center;
//Encapsulate函数重新计算boundsbounds.Encapsulate(mrs[i].bounds);
        }
Vector3min=bounds.min;
Vector3max=bounds.max;
returnIsInRange(points, height, min)
&&IsInRange(points, height, max)
&&IsInRange(points, height, newVector3(min.x, min.y, max.z))
&&IsInRange(points, height, newVector3(min.x, max.y, min.z))
&&IsInRange(points, height, newVector3(max.x, min.y, min.z))
&&IsInRange(points, height, newVector3(min.x, max.y, max.z))
&&IsInRange(points, height, newVector3(max.x, min.y, max.z))
&&IsInRange(points, height, newVector3(max.x, max.y, min.z));
    }
//判断点A是否在凸边体范围内privateboolIsInRange(Transform[] points, floatheight, Vector3A)
    {
boolflag=true;
flag&=A.y<=height* .5f;
flag&=A.y>=-height* .5f;
flag&=IsInRange(points, A);
returnflag;
    }
//判断点A是否在凸边型范围内privateboolIsInRange(Transform[] points, Vector3A)
    {
//取第一条边中点Vector3half01= (points[0].position+points[1].position) * .5f;
//中点延伸(射线)half01+= (half01-A).normalized*100000;
//用于记录交点的个数intcount=0;
//遍历for (inti=0; i<points.Length; i++)
        {
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
//判断是否相交if (IsIntersection(a.position, b.position, A, half01)) count++;
        }
//交点个数为奇数则表示点A在凸边型范围内returncount%2==1;
    }
//判断AB与CD是否相交privateboolIsIntersection(Vector3A, Vector3B, Vector3C, Vector3D)
    {
//A-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign1=Mathf.Sign(Vector3.Cross(A-D, C-D).y);
//B-D与C-D叉积结果大等于0时返回1 小于0时返回-1floatsign2=Mathf.Sign(Vector3.Cross(B-D, C-D).y);
//C-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign3=Mathf.Sign(Vector3.Cross(C-A, B-A).y);
//D-A与B-A叉积结果大等于0时返回1 小于0时返回-1floatsign4=Mathf.Sign(Vector3.Cross(D-A, B-A).y);
//AB与CD相交返回true 否则返回falsereturn!Mathf.Approximately(sign1, sign2) &&!Mathf.Approximately(sign3, sign4);
    }
privatevoidOnDrawGizmos()
    {
if (points.Length<3||obj==null) return;
boolflag=IsInRange(points, height, obj);
Handles.color=flag?Color.cyan : Color.red;
for (inti=0; i<points.Length; i++)
        {
Handles.Label(points[i].position-newVector3(0, height* .5f, 0), $"顶点{i + 1}");
Handles.Label(points[i].position+newVector3(0, height* .5f, 0), $"顶点{i + 1 + points.Length}");
vara=points[i%points.Length];
varb=points[(i+1) %points.Length];
varminA=a.position-newVector3(0, height* .5f, 0);
varmaxA=a.position+newVector3(0, height* .5f, 0);
varminB=b.position-newVector3(0, height* .5f, 0);
varmaxB=b.position+newVector3(0, height* .5f, 0);
Handles.DrawAAPolyLine(minA, minB);
Handles.DrawAAPolyLine(maxA, maxB);
Handles.DrawAAPolyLine(minA, maxA);
Handles.DrawAAPolyLine(minB, maxB);
        }
Boundsbounds=newBounds(Vector3.zero, Vector3.zero);
//获取所有MeshRenderer 包括子物体varmrs=obj.GetComponentsInChildren<MeshRenderer>(true);
Vector3center=Vector3.zero;
for (inti=0; i<mrs.Length; i++)
        {
center+=mrs[i].bounds.center;
//Encapsulate函数重新计算boundsbounds.Encapsulate(mrs[i].bounds);
        }
Vector3point1=bounds.min;
Vector3point2=bounds.max;
Vector3point3=newVector3(point1.x, point1.y, point2.z);
Vector3point4=newVector3(point1.x, point2.y, point1.z);
Vector3point5=newVector3(point2.x, point1.y, point1.z);
Vector3point6=newVector3(point1.x, point2.y, point2.z);
Vector3point7=newVector3(point2.x, point1.y, point2.z);
Vector3point8=newVector3(point2.x, point2.y, point1.z);
Handles.color=Color.yellow;
Handles.DrawLine(point6, point2);
Handles.DrawLine(point2, point8);
Handles.DrawLine(point8, point4);
Handles.DrawLine(point4, point6);
Handles.DrawLine(point3, point7);
Handles.DrawLine(point7, point5);
Handles.DrawLine(point5, point1);
Handles.DrawLine(point1, point3);
Handles.DrawLine(point6, point3);
Handles.DrawLine(point2, point7);
Handles.DrawLine(point8, point5);
Handles.DrawLine(point4, point1);
    }
}

image.gif

目录
相关文章
|
10天前
|
图形学
Unity 获取鼠标位置下的UGUI或3D物体
本文总结了两种检测方法,分别用于UGUI和3D物体的检测。第一种方法`GetOverUIobj`专门用于检测鼠标悬停的UGUI元素,通过`GraphicRaycaster`实现。第二种方法`GetOverWordGameObject`则同时适用于UI和3D物体检测,利用`PhysicsRaycaster`进行射线检测。两者均返回悬停对象或null。
|
10天前
|
图形学
unity 物体震动
在Unity中实现物体震动效果,主要通过改变物体的位置、旋转或缩放属性来模拟震动。以下是位置震动的实现原理及代码示例:通过随机生成微小偏移量并累加到物体位置上,在短时间内不断改变位置产生震动效果。生成随机偏移,并结合时间控制持续震动。
|
10天前
|
前端开发 图形学
unity UGUI跟随3D物体的坐标转换
在 Unity 中实现 UGUI 元素跟随 3D 物体,关键是将 3D 物体的世界坐标转换为屏幕或画布坐标。通过 Camera.WorldToScreenPoint 方法,可将 3D 物体位置映射到屏幕上,再更新 UGUI 元素的位置。代码示例展示了如何使用该方法,使 UGUI 图像跟随 3D 模型,并提供文字显示、图像和线条的显示/隐藏功能。
|
10天前
|
存储 图形学 索引
unity 使物体跟随路径点自动移动位置
在Unity中,物体沿路径点自动移动的核心原理是通过预设路径点,控制物体依次移动。路径点可用空对象或三维向量数组定义,并按顺序存储。移动时,计算当前位置与下一个路径点的向量差以确定方向,使用`Vector3.MoveTowards`逐步靠近目标点。代码实现包括路径点设置、移动控制及插值计算,确保物体平滑移动和旋转。
|
10天前
|
图形学
Unity 射线移动物体Ray
在Unity中,通过射线检测实现3D物体的拖拽和移动。射线由起点和方向组成,使用`Physics.Raycast`检测与物体的交点。点击物体时,记录位置偏移量,拖动过程中更新物体位置。代码包括基本拖拽和上下拖动功能,适用于正交摄像机场景。测试时为物体设置特定标签(如&quot;JQR&quot;)以便区分和操作。 示例代码展示了如何通过鼠标事件控制物体移动,并结合层级掩码优化射线检测。具体实现包括:点击选中物体、拖动更新位置、释放鼠标取消选择。此外,提供了上下拖动的额外功能,通过按键切换模式。
|
10天前
|
图形学 开发者
unity 从工具栏拖动生成物体
在 Unity 中实现从工具栏拖动生成物体的功能,基于编辑器扩展、事件系统和预制体实例化。通过自定义编辑器窗口、处理鼠标事件(按下、移动、释放)及使用 Instantiate 方法,可实现拖动并生成预制体物体。代码示例展示了如何检测鼠标事件并在指定位置实例化物体。
|
6月前
|
图形学
小功能⭐️Unity获取场景中所有物体
小功能⭐️Unity获取场景中所有物体
小功能⭐️Unity获取场景中所有物体
|
6月前
|
前端开发 图形学
Unity精华☀️UI和物体可见性的判断方法
Unity精华☀️UI和物体可见性的判断方法
|
6月前
|
图形学
小功能⭐️获取Unity游戏物体上,所挂载组件的名称
小功能⭐️获取Unity游戏物体上,所挂载组件的名称
|
6月前
|
图形学
小功能⭐️解决Unity无法对一个物体上的所有材质球进行更改
小功能⭐️解决Unity无法对一个物体上的所有材质球进行更改