介绍
是的,这个名字听起来很奇怪。“运动角色”。那是什么?该名称的原因是,当物理引擎问世时,它们被称为“动态”引擎(因为它们主要处理碰撞响应)。为了使用动态引擎创建角色控制器,已经进行了许多尝试,但是这并不像看起来那样容易。Godot是您可以找到的最佳动态角色控制器实现之一(如在2d / platformer演示中所见),但是使用它需要相当水平的技能和对物理引擎的理解(或者非常耐心尝试错误)。
诸如Havok之类的某些物理引擎似乎认为动态角色控制器是最佳选择,而其他物理引擎(PhysX)则更愿意推广运动学引擎。
那么区别是什么呢?:
甲动态字符控制器采用刚性体具有无限惯性张量。这是一个不能旋转的刚体。物理引擎总是让物体移动和碰撞,然后一起解决它们的碰撞。如平台游戏演示所示,这使动态角色控制器能够与其他物理对象无缝交互。但是,这些交互并非总是可预测的。碰撞可能需要一帧以上的时间才能解决,因此一些碰撞似乎只位移了一小部分。这些问题可以解决,但需要一定的技能。
一个运动人物控制器被假定为总是在非碰撞状态开始,并且会一直移动到非冲突状态。如果它开始处于碰撞状态,它将尝试像刚体一样释放自身,但这是例外,而不是规则。这使得它们的控制和运动更加可预测且易于编程。但是,不利的是,除非手动编写代码,否则它们无法直接与其他物理对象进行交互。
这个简短的教程将集中于运动字符控制器。基本上,这是老式的处理冲突的方式(不一定在幕后变得更简单,而是被很好地隐藏起来并作为一个很好的简单API呈现)。
物理过程
为了管理运动体或角色的逻辑,始终建议使用物理过程,因为它在物理步骤之前被调用,并且其执行与物理服务器同步,也总是被称为每秒相同的次数。与使用常规过程相比,这使物理和运动计算的工作方式更具可预测性,如果帧率太高或太低,则常规过程可能会出现尖峰或失去精度。
using Godot; using System; public class PhysicsScript : KinematicBody2D { public override void _PhysicsProcess(float delta) { } }
场景设定
有一些测试,这里的场景(从tilemap的教程) kbscene.zip。我们将为角色创建一个新场景。使用机器人精灵创建一个这样的场景:
您会注意到,我们的CollisionShape2D节点旁边有一个警告图标。这是因为我们尚未为其定义形状。在CollisionShape2D的shape属性中创建一个新的CircleShape2D。单击转到其选项,并将半径设置为30:
注意:如之前在物理教程中所述,物理引擎无法处理大多数形状的比例(仅碰撞多边形,平面和线段有效),因此请始终更改形状的参数(例如半径),而不是缩放它。运动/刚体/静态物体本身也是如此,因为它们的比例会影响形状比例。
现在,为角色创建一个脚本,上面用作示例的脚本应作为基础。
最后,在tilemap中实例化该角色场景,并将其作为主要场景,以便在按下play时运行。
运动学特征
回到角色场景,打开脚本,魔术开始了!运动体默认情况下不执行任何操作,但它具有一个有用的功能,称为 KinematicBody2D.move_and_collide()。此函数将Vector2用作参数,然后尝试将该运动应用于运动体。如果发生碰撞,它会在碰撞发生时立即停止。
因此,让我们向下移动精灵,直到它掉到地上:
using Godot; using System; public class PhysicsScript : KinematicBody2D { public override void _PhysicsProcess(float delta) { // Move down 1 pixel per physics frame MoveAndCollide(new Vector2(0, 1)); } }
结果是角色将移动,但在撞击地板时会立即停止。太酷了吧?
下一步是将重力添加到混合中,这样,它的行为就有点像常规游戏角色:
using Godot; using System; public class PhysicsScript : KinematicBody2D { const float gravity = 200.0f; Vector2 velocity; public override void _PhysicsProcess(float delta) { velocity.y += delta * gravity; var motion = velocity * delta; MoveAndCollide(motion); } }
现在,角色平稳滑落。让我们在触摸方向键时向左右两侧行走。请记住,所使用的值(至少对于速度而言)是像素/秒。
这可以通过向左和向右按下来增加简单的步行支撑:
using Godot; using System; public class PhysicsScript : KinematicBody2D { const float gravity = 200.0f; const int walkSpeed = 200; Vector2 velocity; public override void _PhysicsProcess(float delta) { velocity.y += delta * gravity; if (Input.IsActionPressed("ui_left")) { velocity.x = -walkSpeed; } else if (Input.IsActionPressed("ui_right")) { velocity.x = walkSpeed; } else { velocity.x = 0; } // We don't need to multiply velocity by delta because "MoveAndSlide" already takes delta time into account. // The second parameter of "MoveAndSlide" is the normal pointing up. // In the case of a 2D platformer, in Godot, upward is negative y, which translates to -1 as a normal. MoveAndSlide(velocity, new Vector2(0, -1)); } }