在游戏开发中,您通常需要知道游戏中的两个对象何时相交或接触。这就是所谓的碰撞检测。当检测到碰撞时,您通常希望发生某些事情。这就是所谓的碰撞响应。
Godot在2D和3D中提供了许多碰撞对象,以提供碰撞检测和响应。试图确定要为您的项目使用哪个选项可能会造成混淆。如果您了解每个工作原理以及各自的优缺点,则可以避免问题并简化开发。
在本指南中,您将学习:
戈多的四种碰撞对象类型
每个碰撞对象如何工作
什么时候以及为什么要选择一种而不是另一种
注意
本文档的示例将使用2D对象。每个2D物理对象和碰撞形状在3D中具有直接等效的功能,并且在大多数情况下,它们的工作方式几乎相同。
碰撞对象
Godot提供了四种物理体,扩展了CollisionObject2D:
Area2D
Area2D节点提供检测和影响。它们可以检测物体何时重叠,并可以在物体进入或离开时发出信号。Area2D 还可以使用an来覆盖定义区域中的物理特性,例如重力或阻尼。
其他三个主体扩展了PhysicsBody2D:
StaticBody2D
静态物体是物理引擎不会移动的物体。它参与碰撞检测,但不会响应碰撞而移动。它们最常用于环境中的对象或不需要任何动态行为的对象。
RigidBody2D
这是实现模拟2D物理的节点。您无需RigidBody2D直接控制a ,而是要对其施加力(重力,脉冲等),然后物理引擎将计算最终的运动。阅读更多有关使用刚体的信息。
KinematicBody2D
提供碰撞检测但没有物理学的物体。所有运动和碰撞响应都必须用代码实现。
碰撞形状
物理物体可以将任意数量的Shape2D对象作为子对象。这些形状用于定义对象的碰撞范围并检测与其他对象的接触。
注意
为了检测碰撞,Shape2D必须至少分配一个对象。
分配形状的最常见方法是添加CollisionShape2D 或CollisionPolygon2D作为对象的子级。这些节点允许您直接在编辑器工作区中绘制形状。
重要
注意不要在编辑器中缩放碰撞形状。 检查器中的“比例”属性应保留为(1,1)。
更改碰撞形状的大小时,应始终使用大小控制柄,而不是Node2D比例控制柄。 缩放形状会导致意外的碰撞行为。
物理过程回调
物理引擎可以产生多个线程以提高性能,因此它最多可以使用一个完整的帧来处理物理。 因此,对于当前帧,身体的状态变量(例如位置或线速度)的值可能不准确。
为了避免这种不准确性,任何需要访问人体属性的代码都应在Node._physics_process() 回调中运行,该回调在每个物理步骤之前以恒定帧速率(默认为每秒60次)被调用。该方法将被传递一个delta 参数,该参数是一个浮点数,它等于自上一步以来经过的时间(以 秒为单位)。当使用默认的60 Hz物理更新速率时,通常等于0.01666…(但不总是如此,请参见下文)。
注意
建议始终delta在物理计算中使用相关参数,以便在您更改物理更新率或玩家的设备无法跟上时,游戏能够正确运行。
碰撞层和蒙版
碰撞层系统是最强大但经常被误解的碰撞特征之一。该系统使您可以在各种对象之间建立复杂的交互。关键概念是图层 和蒙版。每个CollisionObject2D都有可与之交互的20个不同的物理层。
让我们依次查看每个属性:
碰撞层
这描述了对象出现在的层。默认情况下,所有实体都在layer上1。
碰撞面罩
这描述了身体将扫描碰撞的层。如果对象不在遮罩层之一中,则主体将忽略它。默认情况下,所有实体都扫描layer 1。
这些属性可以通过代码或在检查器中编辑来配置。
跟踪每个图层的用途可能很困难,因此您可能会发现为使用的图层分配名称很有用。可以在项目设置->图层名称中分配名称。
GUI示例
游戏中有四种节点类型:墙,玩家,敌人和硬币。玩家和敌人都应与墙碰撞。播放器节点应同时检测到与敌人和硬币的碰撞,但敌人和硬币应互相忽略。
首先命名第1-4层“墙”,“玩家”,“敌人”和“硬币”,然后使用“层”属性将每个节点类型放置在其相应的层中。然后通过选择每个节点应与之交互的层来设置每个节点的“蒙版”属性。例如,播放器的设置如下所示:
代码示例
在函数调用中,将图层指定为位掩码。如果功能默认启用所有图层,则图层蒙版将指定为0x7fffffff。您的代码可以对图层蒙版使用二进制,十六进制或十进制表示法,具体取决于您的偏好。
上面启用了第1、3和4层的示例的等效代码如下:
# Example: Setting mask value for enabling layers 1, 3 and 4 # Binary - set the bit corresponding to the layers you want to enable (1, 3, and 4) to 1, set all other bits to 0. # Note: Layer 20 is the first bit, layer 1 is the last. The mask for layers 4,3 and 1 is therefore 0b00000000000000001101 # (This can be shortened to 0b1101) # Hexadecimal equivalent (1101 binary converted to hexadecimal) 0x000d # (This value can be shortened to 0xd) # Decimal - Add the results of 2 to the power of (layer be enabled-1). # (2^(1-1)) + (2^(3-1)) + (2^(4-1)) = 1 + 4 + 8 = 13 pow(2, 1) + pow(2, 3) + pow(2, 4)