Area2D
区域节点提供检测和影响。它们可以检测物体何时重叠并在物体进入或离开时发出信号。区域还可以用于覆盖定义区域中的物理属性,例如重力或阻尼。
Area2D有三个主要用途:
给定区域中的替代物理参数(例如重力)。
检测其他物体何时进入或离开区域或当前区域中有哪些物体。
检查其他区域是否重叠。
默认情况下,区域还接收鼠标和触摸屏输入。
StaticBody2D
静态物体是物理引擎不会移动的物体。它参与碰撞检测,但不会响应碰撞而移动。但是,它可以利用其和属性为碰撞的物体提供运动或旋转,就好像它在运动一样。constant_linear_velocityconstant_angular_velocity
StaticBody2D 节点最常用于环境中的对象或不需要任何动态行为的对象。
示例用于StaticBody2D:
平台(包括移动平台)
输送带
墙壁和其他障碍
RigidBody2D
这是实现模拟2D物理的节点。您不能直接控制 RigidBody2D。取而代之的是,您对其施加力,然后物理引擎会计算出最终的运动,包括与其他物体的碰撞以及碰撞响应(如弹跳,旋转等)。
您可以通过“质量”,“摩擦”或“弹跳”之类的属性来修改刚体的行为,这些属性可以在检查器中设置。
人体的行为也会受到世界属性(如在“ 项目设置”->“物理”中设置的)的影响,或者受输入 覆盖全球物理属性的Area2D的影响。
当刚体处于静止状态并且一段时间未移动时,它将进入睡眠状态。睡眠物体的作用类似于静态物体,其力不是由物理引擎计算的。当通过碰撞或通过代码施加力时,身体将醒来。
刚体模式
刚体可以设置为以下四种模式之一:
刚性-身体表现为物理对象。它会与其他物体碰撞,并对其施加的力作出反应。这是默认模式。
静态-主体的行为类似于StaticBody2D,并且不会移动。
角色-与“刚性”模式相似,但身体无法旋转。
运动-身体的行为类似于KinematicBody2D,必须通过代码移动。
使用RigidBody2D
使用刚体的好处之一是无需编写任何代码即可“免费”获得许多行为。例如,如果您要制作带有下降块的“愤怒的小鸟”式游戏,则只需创建RigidBody2Ds并调整其属性。堆积,下落和弹跳将由物理引擎自动计算。
但是,如果你想有过身体有一定的控制,你应该照顾-改变position,linear_velocity,刚体的或其他物理性质可能会导致意外的行为。如果您需要更改任何与物理学相关的属性,则应使用_integrate_forces() 回调而不是_physics_process()。在此回调中,您可以访问人体的Physics2DDirectBodyState,它可以安全地更改属性并将其与物理引擎同步。
例如,以下是“小行星”式太空飞船的代码:
class Spaceship : RigidBody2D { private Vector2 _thrust = new Vector2(0, 250); private float _torque = 20000; public override void _IntegrateForces(Physics2DDirectBodyState state) { if (Input.IsActionPressed("ui_up")) SetAppliedForce(_thrust.Rotated(Rotation)); else SetAppliedForce(new Vector2()); var rotationDir = 0; if (Input.IsActionPressed("ui_right")) rotationDir += 1; if (Input.IsActionPressed("ui_left")) rotationDir -= 1; SetAppliedTorque(rotationDir * _torque); } }
请注意,我们不是 直接设置linear_velocity或angular_velocity属性,而是将力(thrust和torque)施加到物体上,然后让物理引擎计算出所产生的运动。
注意
当刚体进入睡眠状态时,_integrate_forces()
将不会调用该功能。要覆盖此行为,您将需要通过创建碰撞,向其施加力或禁用can_sleep
属性来使身体保持清醒状态。请注意,这可能会对性能产生负面影响。
联系人报告
默认情况下,刚体不跟踪接触,因为如果场景中有很多刚体,这可能需要大量的内存。若要启用联系人报告,请将contacts_reported 属性设置为非零值。然后可以通过Physics2DDirectBodyState.get_contact_count()和相关函数来获取联系人 。
可以通过contact_monitor 属性启用通过信号的接触监视。有关可用信号的列表,请参见RigidBody2D。
KinematicBody2D
KinematicBody2D实体可以检测与其他实体的碰撞,但不受重力或摩擦等物理属性的影响。相反,它们必须由用户通过代码控制。物理引擎不会移动运动体。
移动运动机构时,请勿position直接设置它。而是使用move_and_collide()ormove_and_slide()方法。这些方法沿着给定的矢量移动物体,如果检测到与另一个物体的碰撞,它将立即停止。身体碰撞后,任何碰撞响应都必须手动编码。
运动碰撞响应
发生碰撞后,您可能希望身体反弹,沿墙滑动或改变其撞击的对象的属性。处理碰撞响应的方式取决于您用来移动KinematicBody2D的方法。
move_and_collide
使用时move_and_collide(),该函数返回 KinematicCollision2D对象,该对象包含有关碰撞和碰撞体的信息。您可以使用此信息来确定响应。
例如,如果要查找空间中发生碰撞的点:
class Body : KinematicBody2D { private Vector2 _velocity = new Vector2(250, 250); public override void _PhysicsProcess(float delta) { var collisionInfo = MoveAndCollide(_velocity * delta); if (collisionInfo != null) { var collisionPoint = collisionInfo.GetPosition(); } } }
或从碰撞对象反弹:
class Body : KinematicBody2D { private Vector2 _velocity = new Vector2(250, 250); public override void _PhysicsProcess(float delta) { var collisionInfo = MoveAndCollide(_velocity * delta); if (collisionInfo != null) _velocity = _velocity.Bounce(collisionInfo.Normal); } } move_and_slide
滑动是一种常见的碰撞反应。想象一个玩家在自上而下的游戏中沿着墙壁移动,或者在平台游戏中在斜坡上上下移动。虽然可以使用后,自己编写这种反应move_and_collide(), move_and_slide()提供了实现滑动,而无需编写大量代码的便捷方式。
警告
move_and_slide()自动包括在计算中时间步长,所以应该没有乘法的速度矢量通过delta。
例如,使用以下代码制作一个可以在地面上行走(包括斜坡)并在站立在地面上时可以跳跃的角色:
class Body : KinematicBody2D { private float _runSpeed = 350; private float _jumpSpeed = -1000; private float _gravity = 2500; private Vector2 _velocity = new Vector2(); private void GetInput() { _velocity.x = 0; var right = Input.IsActionPressed("ui_right"); var left = Input.IsActionPressed("ui_left"); var jump = Input.IsActionPressed("ui_select"); if (IsOnFloor() && jump) _velocity.y = _jumpSpeed; if (right) _velocity.x += _runSpeed; if (left) _velocity.x -= _runSpeed; } public override void _PhysicsProcess(float delta) { _velocity.y += _gravity * delta; GetInput(); _velocity = MoveAndSlide(velocity, new Vector2(0,-1)); } }
有关使用的更多详细信息,请参见运动字符(2D)move_and_slide(),包括带有详细代码的演示项目。