❶ 3D游戏是怎么检测碰撞的
首先假设你对与碰撞检测相关的几何和数学知识已经有了基本的了解。在文章的最后,我将提供一些这方面的参考资料,以免你对它们感觉有点生疏。另外我还假设你已经读过 Jeff Lander 的图形专栏里关于碰撞检测文章(“Crashing into the New Year,” ; “When Two Hearts Collide,”;和 “Collision Response: Bouncy, Trouncy, Fun,”)。我将首先进行一个大概的描述,然后快速地切入到核心内容里,通过这两步从上至下地深入到碰撞检测中。我将讨论两种类型的图形引擎中的碰撞检测:基于 portal 的和基于 BSP 的。每种引擎中多边形的组织各不相同,因此在 world-object 型的碰撞检测上存在很大的差别。而object-object 型的碰撞检测绝大多数地方在上述两种引擎里的是一样的,主要看你是如何实现的了。当我们接触到多边形的碰撞检测时,我们还会实验如何将其扩展到我们学过的凸型物体上。
为了创建一个理想的碰撞检测程序,我们不得不在开发一个游戏的的图形管道的同时就开始计划并创建它的框架。在项目的最后加入碰撞检测是相当困难的。想在开发周期的末尾创建快速的碰撞检测将很有可能会使整个游戏被毁掉,因为我们不可能使它能高效地运行。在好的游戏引擎中,碰撞检测应该是精确、有效并且十分快速的。这些要求意味着碰撞检测将要与场景的多边形管理管道紧紧地联系起来。这也意味着穷举法将无法工作??今天的3D游戏中每帧处理的数据量很可能导致打格,当你还在检测一个物体的各多边形是否与场景中的其它多边形碰撞时,时间已经过去了。
让我们从基本的游戏引擎循环开始吧(列表1)。快速浏览这些代码来得到碰撞检测的相关策略。我们先假设碰撞没有发生,然后更新物体的位置,如果发现发生了碰撞,我们将把物体移回原来的位置不允许它穿越边界(或将物体销毁或执行一些预防措施)。然而,这个假设太过简单因为我们无法得知物体原来的位置是否仍然有效。你必须为这种情况设计一个方案(否则你可能会体验到坠机或被子弹击中的感觉??就是前面举的例子)。如果你是一个热心的玩家,你可能已经注意到了在一些游戏当中,当你挨着墙壁并试图穿过去的时候,摄像机就开始震动。你正经历的就是将主角移回原位的情况。震动是因为取了较大的时间片引起的。
Listing 1. Extremely Simplified Game Loop
while(1){
process_input();
update_objects();
render_world();
}
update_objects(){
for (each_object)
save_old_position();
calc new_object_position
{based on velocity accel. etc.}
if (collide_with_other_objects())
new_object_position = old_position();
{or if destroyed object remove it etc.}
Figure 1. Time gradient and collision tests.
但是我们的方法有缺陷,我们忘了在等式中加入时间。图1告诉我们时间太重要了不能忘了它。即便物体在 t1 或 t2 时刻没有发生碰撞,它仍有可能在 t 时刻穿过边界(t1
我们可以把时间看成是第四维并将所有运算在4维空间中进行。然而这可能会让运算变得十分复杂,所以我们会避开这些。我们还可以创建一个以 t1、t2时刻的物体为起始点的实心体,然后用它来与墙进行测试(见图2)Figure 2. Solid created from the space that an object spans over a given time frame.
一个简单的方法就是创建一个凸壳来罩住两个不同时刻的物体。这种方法效率低下可能会明显地降低你的游戏速度。以其创建一个凸壳,还不如创建一个围绕实心体的包围盒。我们学习其它的技术后再回来讨论这个问题。
有另一种比较容易执行但精度较低的方法,就是把给定的时间段分为两分,然后测试时间中点的相交关系。我们还可以递归地依次测定各段的时间中点。这个方法比先前的方法要快得多,但不能保证能捕捉到所有的碰撞情况。另一个暗藏着的问题是collide_with_other_objects()方法的实现??即判断一个物体是否与场景中的其它物体相交。如果场景中有很多的物体,这个方法可能消耗很大。如果要判断各物体与场景中其它物体是否相交,我们将不得不进行大概N选2次比较。因此比较次数会是N的平方次?(或表示成O(N2))。但我们可以用几种方法来避免进行O(N2)对的比较。举个例子,我们可以把场景中的物体分成静态的(被撞物)和动态的(碰撞物??即使它的速度为0也行)。就好象房间中的墙壁是被撞物,而一个扔向墙壁的小球是碰撞物。我们可以创建两棵独立的树(每一棵对应一类物体),然后测试那些物体可能会碰撞的树。我们甚至可以对环境进行约定让一些碰撞物之间不发生碰撞??比如我们不需要在两颗子弹之间进行判断。现在在继续之前,(经过改进之后)我们可以说处理过程变得更加清晰了。(另一个减少场景中成对的比较的方法就是建立八叉树。这已经超出了这篇文章的范围,你可以在Spatial Data Structures: Quadtree, Octrees and Other Hierarchical Methods文章中的For Further Info一节里读到更多关于八叉的信息)。现在让我们来看一下基于 Portal 引擎,了解为什么在这类引擎中一提到碰撞检测就会那么痛苦。
Portal引擎和Object-Object型碰撞
基于 Portal 的引擎把场景或世界分割成较小的凸方形区域。凸方形区域很适合图形管道因为它们能避免重绘现象。不幸的是,对碰撞检测来说,凸方形区域会给我们带来一些困难。在我最近的一些测试中,一个引擎中平均大约有400到500个凸方形区域。当然,这个数字会随着不同的引擎而有所变化,因为不同的引擎使用不同的多边形技术。而且多边形的数目也会因场景的大小而有所不同。
判断一个物体的多边形是否穿过了场景中的多边形产生的运算量可能会很大。一个最简单的碰撞检测法就是用球形来近似地表示物体或物体的一部分,然后再判断这些包围球是否相交。这样我们仅仅需要测试两个球体中心的距离是否小于它们的半径合(这表示发生了碰撞)。如果我们是用中心点距离的平方和半径合的平方进行比较,那更好,这样我们可以在计算距离时除去拙劣的开方运算。但是,简单的运算也导致了精确度的降低(见图3)。
Figure 3. In a sphere-sphere intersection, the routine may report that collision has occurred when it really hasn’t.
但我们仅仅是将这个不太精确的方法做为我们的第一步。我们用一个大的球体代表整个对象,然后检测它是否和其它的球体相交。如果检测到发生了碰撞,那么我们就要进一步提高精度,我们可以将大的球体分割成一系列小的球体,并检查与各小球体是否发生碰撞。我们不断地分割检查直到得到满意的近似值为止。分层并分割的基本思想就是我们要尽可能达到适合需要的理想的情况。
Figure 4. Sphere subdivision.
用球体去近似地代表物体运算量很小,但在游戏中的大多数物体是方的,我们应该用方盒来代表物体。开发者一直用包围盒和这种递归的快速方法来加速光线追踪算法。?谑导手校�庑┧惴ㄒ丫�园瞬婧虬ABB(axis-aligned bounding boxes)的方式出现了。图5展示了一个AABB和它里面的物体。Figure 5. An object and its AABB.
坐标轴平行(“Axis-aligned”)不仅指盒体与世界坐标轴平行,同时也指盒体的每个面都和一条坐标轴垂直。这样一个基本信息就能减少转换盒体时操作的次数。AABBs 在当今的许多游戏中都得到了应用,开发者经常用它们作为模型的包围盒。再次指出,提高精度的同时也会降低速度。因为 AABBs 总是与坐标思平行,我们不能在旋转物体的时候简单地旋转 AABBs --- 它们应该在每一帧都重新计算过。如果我们知道每个对象的内容,这个计算就不算困难并不会降低游戏的速度。 然而,我们还面临着精度的问题。假如我们有一个3D的细长刚性直棒,并且要在每一帧动画中都重建它的AABB。我们可以看到每一帧中的包围盒的都不一样而且精度也会随之改变。
❷ 碰撞检测的原理是什么virtools中提供了几种碰撞检测的方法有何不同
四班童鞋,按检测方式又可以分为离散点的碰撞检测和连续碰撞检测(CCD continuous collision detection)。离散点的碰撞检测是指定某一时刻T的两个静态碰撞体,看它们之间是否交迭,如果没有交迭则返回它们最近点的距离,如果交迭则返回交迭深度,交迭方向等。连续碰撞检测则是分别指定在T1、T2两个时刻两个碰撞体的位置,看它们在由T1运动到T2时刻的过程中是否发生碰撞,如果碰撞则返回第一碰撞点的位置和法线。连续碰撞检测是最为自然的碰撞检测,可以大大方便碰撞响应逻辑的编写,可以很容易避免物体发生交迭或者穿越。离散点的碰撞检测则没有那么友好,当检测到碰撞时两个物体已经发生了交迭,如果其中有三角形网格对象那么已经有许多三角形发生了交迭,如何将两个交迭的对象分开并按合理的方式运动是一个挑战。虽然连续碰撞检测是最自然的方式,但它的实现非常复杂,运算开销也很大,所以目前大部分成熟的物理引擎和碰撞检测引擎还是采用了基于离散点的碰撞检测,为了避免物体交迭过深或者彼此穿越,大多都要采用比较小的模拟步长。
❸ unity 怎么判断碰撞的物体
发生碰撞条件如下:
两个对象都有Collider组件且至少一个有Rigidbody组件其中至少一个物体(必须运动的)必须带有碰撞器(collider)+刚体(Rigidbody),另一个物体(可以静止也可以运动)也必须至少带collider也有说一方有CharacterController,另一方有Collider。
详解如下:
(1)添加了CharacterController组件后,人物将不受力影响,这时即使加上Rigidbody组件,并启用Use Gravity。人物也不会受重力影响,在脚本中通过rigidbody对人物施加力也是无效的。
也就是说CharacterController屏蔽了Rigidbody的所有属性和方法。要控制CharacterController移动,可以通过在脚本中调用Move方法使其移动。
(2)虽然CharacterController不受力,但是有个例外是,它受碰撞的影响。
一般的碰撞发生条件是:碰撞的两个物体必须都有Collider,并且其中一个有Rigidbody。
但是如果一方有CharacterController,则不需要。
这时碰撞发生的条件为:一方有CharacterController,另一方有Collider。CharacterController本身就继承自Collider。
(3)碰撞发生时,CharacterController不会推动其它物体移动,也就是说CharacterController不会对它所碰撞的物体施加物理作用。除非我们在脚本中添加了OnControllerColliderHit()函数,在该函数中使用被碰撞物体的rigidbody对被碰撞物体施加力。
(3)碰撞体的检测方法扩展阅读:
如何学习unity:
第一步首先了解unity3d的菜单,视图界面。这些是最基本的基础,可以像学word操作一样,大致能明白有几个菜单,几个基本的视图,各自起什么作用的就可以了。当然还要了解人物基本的比例和结构。
第二步理解场景里面的坐标系统,输入系统,简单的向量概念。Unity3D的坐标系统及向量概念如果不理解清楚,不理解世界坐标,局部坐标的关系,即使一个简单的移动,缩放,旋转的几行代码,也会困惑你半天。
第三步学习创建基本的场景的一些基本概念:游戏对象,组件,脚本。在界面上分别体现在层次视图,项目视图及属性视图,要理清楚彼此之间的关系
第四步学习资源导入方面的一些基本元素:网格,材质,贴图,动画等。
第五步学习脚本的生命周期,Start,UpDate,ONGUI这些基本的方法。了解,预制,时间,数学等常用的类及相关方法。理解游戏对象,组件,脚本彼此之间的关系。
第六步进一步学习摄像机,灯光,地形,渲染,粒子系统,物理系统等等,这些每一个深入进去都是一个很复杂的主题。
第七步一些更高级的概念:向量的加减法点乘叉乘,光照法线贴图,内存管理,图形优化等等。Unity3D入门容易,真的要精通,那是相当难的。
❹ Unity 3D中碰撞检测中有多少个方法(送分的)
OnTriggerEnter
OnTriggerEnter is called when the Collider other enters the trigger.
OnTriggerExit
OnTriggerExit is called when the Collider other has stopped touching the trigger.
OnTriggerStay
OnTriggerStay is called almost all the frames for every Collider other that is touching the trigger.
OnCollisionEnter
OnCollisionEnter is called when this collider/rigidbody has begun touching another rigidbody/collider.
OnCollisionExit
OnCollisionExit is called when this collider/rigidbody has stopped touching another rigidbody/collider.
OnCollisionStay
OnCollisionStay is called once per frame for every collider/rigidbody that is touching rigidbody/collider.
基本就是这些,
1,开始接触到其他碰撞体
2,持续接触其他碰撞体
3,停止接触其他碰撞体
❺ 怎么检测物体和边界的碰撞
也带来了一个新的问题:摄像头移动的时候,毫无阻拦,这就是所谓的“穿墙模式”。有没有什么办法解决这个问题呢?有,就是在移动摄像头前先进行“碰撞检测”,确定摄像头的新位置区间中没有其他的三维模型。本文将介绍如何在WPF中进行三维碰撞检测。利用Rect3D.IntersectsWith 方法在进入下一节前,先看看最简单的碰撞检测方式:利用Rect3D.IntersectsWith 方法。Model3D有一个Bounds属性,用来表示该Model3D的边界:该属性是Rect3D类型的,我们可以使用IntersectsWith 来确定相机位置所在的矩形是否与此Rect3D相交。如果是,则说明相机移动到Rect3D内部,冲突发生;如果否,则表示相机离Model3D还有一段距离,可以放心地移动。没有发生碰撞发生碰撞的情况使用Rect3D.IntersectsWith 方法,对于规规矩矩的正方体来说,效果很好。但是如果使用Rect3D.IntersectsWith 方法检测摄像机是否和不规则物品的外接多边形发生碰撞,精确性会降低很多。就拿上图来说,红色方块所在的摄像机实际上和房子还有很远一段距离,但却在房子所在区域里,这个时候,Rect3D.IntersectsWith 检测的结果是“碰撞发生了”。因此,需要用稍微复杂一点的方法,VisualTreeHelper.HitTest方法,对三维物品进行命中测试,以处理不规则物品的碰撞检测问题。利用VisualTreeHelper.HitTest 方法VisualTreeHelper.HitTest是由三个函数重载而成的,在三维世界里,使用:public static void HitTest( Visual3D reference, HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback, HitTestParameters3D hitTestParameters ) 方法来进行命中测试。reference:要进行命中测试的 Visual3D。 也就是场景中的不规则的三维物品。filterCallback:表示命中测试筛选回调值的方法,有时候,并非所有的三维物品都是不可穿越的,例如泳池中的水,在没有结冰的前提下是阻止不了Camera移动的,因此,可以filterCallback设置这些物体。resultCallback:表示命中测试结果回调值的方法。hitTestParameters:要进行命中测试的三维参数值。对于最后一个参数,hitTestParameters,使用的是HitTestParameters3D的一个子类:RayHitTestParameters(也是目前HitTestParameters3D的唯一子类)。该类表示一个射线。看到这里,你大体会意思到如何使用VisualTreeHelper.HitTest来进行碰撞检测了吧。没错!
❻ 如何检测一个物体是否与别的物体碰撞
使用Raycaster进行碰撞检测
用Raycaster来检测碰撞的原理很简单,我们需要以物体的中心为起点,向各个顶点(vertices)发出射线,然后检查射线是否与其它的物体相交。如果出现了相交的情况,检查最近的一个交点与射线起点间的距离,如果这个距离比射线起点至物体顶点间的距离要小,则说明发生了碰撞。
这个方法有一个 缺点 ,当物体的中心在另一个物体内部时,是不能够检测到碰撞的。而且当两个物体能够互相穿过,且有较大部分重合时,检测效果也不理想。
还有需要 注意 的一点是:在Three.js中创建物体时,它的顶点(veritces)数目是与它的分段数目相关的,分段越多,顶点数目越多。为了检测过程中的准确度考虑,需要适当增加物体的分段。
❼ unity3d 怎么检测碰撞比如主角碰撞到物体之后销毁被撞到的物体
首先创建一个“立方体”与一个“粒子系统”,立方体在粒子可以碰撞到的范围内。
选择粒子系统,在属性中“Tag”中选择“Add Tag”添加一个“aa”。
勾选“shape”,其中的shape设置为“Box”。
勾选“Collision”,选择“Word”,勾选“Send Collision Message”。
创建脚本,添加“OnParticleCollision”方法,通过aa这个tag判断粒子碰撞。
把脚本放在立方体上。
现在ctrl+p运行游戏,我们发现console中会显示我们设置的碰撞提示,这就表示粒子系统粒子碰撞检测成功了。
❽ c++ 游戏碰撞检测怎么做
在游戏开发中,经常需要进行碰撞检测算法的实现,例如判断前面是否有障碍以及判断子弹是否击中飞机,都是检测两个物体是否发生碰撞,然后根据检测的结果通过碰撞检测算法做出不同的处理。
进行碰撞检测算法的物体可能有些的形状和复杂,这些需要进行组合碰撞检测,就是将复杂的物体处理成一个一个的基本形状的组合,然后分别进行不同的检测。
下面简单介绍一下两种最基本的形状进行碰撞的时候进行的处理。
1、矩形和矩形进行碰撞检测算法
一般规则的物体碰撞都可以处理成矩形碰撞,实现的原理就是检测两个矩形是否重叠。我们假设矩形1的参数是:左上角的坐标是(x1,y1),宽度是w1,高度是h1;矩形2的参数是:左上角的坐标是(x2,y2),宽度是w2,高度是h2。
在检测时,数学上可以处理成比较中心点的坐标在x和y方向上的距离和宽度的关系。即两个矩形中心点在x方向的距离的绝对值小于等于矩形宽度和的二分之一,同时y方向的距离的绝对值小于等于矩形高度和的二分之一。下面是数学表达式:
x方向:| (x1 + w1 / 2) – (x2 + w2/2) | < |(w1 + w2) / 2|
y方向:| (y1 + h1 / 2) – (y2 + h2/2) | < |(h1 + h2) / 2|
在Java ME程序中,只需要将上面的条件转换成代码就可以实现了。
但是矩形碰撞只是一种比较粗糙的碰撞检测算法,因为很多实际的物体可能不是一个规则的矩形。
下面介绍一下圆形碰撞。
2、圆形和圆形的碰撞检测算法
圆形和圆形的碰撞应该说是一种最简单的碰撞,因为在数学上对于两个圆形是否发生重叠,有计算两个圆心之间的距离的公式。那么条件就变为:计算两个圆心之间的距离是否小于两个圆的半径和。
假设圆形1的左上角坐标是(x1,y1),半径是r1,圆形2的左上角的坐标是(x2,y2),半径是r2。
因为MIDP1.0中没有浮点数,而且浮点数的运算比较慢,所以我们将条件做一个简单的变换:对于条件的两边都进行平方,这样就去掉了开方的运算步骤。
下面是数学表达式:
(x1 – x2)2 + (y1 – y2)2 < (r1 + r2)2
在Java ME程序中,只需要将上面的条件转换成代码就可以了。
上面介绍的只是最基本的碰撞检测算法的实现,而实际的编程过程中遇到的碰撞检测问题要比这些复杂很多,还需要其他形式的检测,还需要进行更加深入的学习。
❾ 使用射线Raycast判断某个方向是否有碰撞体
public class NewBehaviourScript : MonoBehaviour {
void Start () {
if (Physics2D.Raycast(this.transform.position, Vector2.down, 10.0f,
1 << LayerMask.NameToLayer("Collider"))) {
string colliderName = Physics2D.Raycast(this.transform.position, Vector2.down, 10.0f,
1 << LayerMask.NameToLayer("Collider")).collider.gameObject.name;
Debug.Log("Collider " + colliderName + " is under the CubeUp");
}
else {
Debug.Log("No collider is under the CubeUp");
}
}
void Update () {
}
}
可以看到这里需要把下方物体CubuDown的Layer设置为Collider(上方物体CubeUp不需要设置):
运行后:
即可以检测到下方有碰撞体。
❿ 一个物体上有多个碰撞体,碰撞体如何检测
.版本 2 .支持库 iext2 .程序集 窗口程序集1 .程序集变量 汽车A, 整数型 .程序集变量 汽车B, 整数型 .程序集变量 变量2, 整数型 【需要用到的变量】 .子程序 __启动窗口_创建完毕 汽车A = 动画框1.创建物体 (, 1, 1, 真, ) 汽车B = 动画框1.创。