将 KinematicBody2D 移动到已知位置godot

问题描述

我在 godot 和物理过程中制作了一个平台游戏,我正在获取玩家的位置,以便我可以将敌人移动到它(它在敌人的脚本中,但我无法弄清楚如何使用 {{1}获取位置 但是当我向玩家移动并滑动时,它给了我一个错误。(顺便说一句,这是一个平台游戏,所以如果该方法增加了重力会很好)

基础“KinematicBody2D (enemy.gd)”中的类型函数“move_and_slide”无效。无法将参数 2 从 float 转换为 Vector2。

(如果这样就好了

解决方法

让我们先看看 documentation of move_and_slide。这是函数的签名:

Vector2 move_and_slide ( Vector2 linear_velocity,Vector2 up_direction=Vector2( 0,0 ),bool stop_on_slope=false,int max_slides=4,float floor_max_angle=0.785398,bool numeric_inertia=true )

注意:

  • 第一个参数是一个速度向量。
  • 第二个参数是一个向上向量。

因此,此功能不适用于职位。

你得到的错误是因为你在 up 参数上传递了一个浮点数。


为什么 move_and_slide 使用 up 向量?这是因为 move_and_slide 更新了您从 is_on_ceilingis_on_flooris_on_wall 获得的值。它如何知道什么是天花板、地板或墙壁?没错,它需要知道它的上升方式。如果你让向上向量为零(或者只是不通过它,因为这是默认值),它们都被认为是墙(这对于自上而下的游戏来说是可以的)。


现在,您想做一个平台游戏,大概是横向卷轴游戏。您很可能希望将 Vector2.UP 作为第二个参数传递。这应该可以修复错误。


然而,你又在偷偷问另一个问题。一种更适合gamedev.stackexchange.com您可以在那里提问(不一定是您遇到错误)。

因此,您想要实现一个具有重力的运动体来追逐玩家。让我们从重力开始……

具有重力的运动体的运行代码如下所示:

extends KinematicBody2D

export(Vector2) var velocity:Vector2
export(float) var gravity:float = 100

func _physics_process(delta:float) -> void:
    velocity.y += gravity * delta
    velocity = move_and_slide(velocity,Vector2.UP)

好吧,gravity 可能不是 100。但这是代码的基本结构。请注意距离单位 - 作为 2D 游戏 - 以像素为单位,而 delta 以秒为单位。因此,gravity 以每秒平方像素为单位。


并且您想追逐玩家头像。为了实现这一点,我将进行以下更改:

  • 参考玩家头像。
  • 将速度分成垂直和水平分量。
  • 具有水平速度。
extends KinematicBody2D

export(NodePath) var player_path:NodePath = @"/root/World/Player"
export(float) var horizontal_speed:float = 100
export(float) var gravity:float = 100

onready var player:Node2D = get_node(player_path)
var _velocity:float = 0

func _physics_process(delta:float) -> void:
    _velocity.y += gravity * delta
    _velocity = move_and_slide(_velocity,Vector2.UP)
    var direction_to_player = transform.origin.direction_to(player.transform.origin)
    _velocity.x = direction_to_player.x * horizontal_speed

此代码使用 NodePath 来查找玩家头像。它在就绪时查询,并从那里开始使用该引用。假设玩家总是在那里,那没问题。

horizontal_speed 指定它向玩家水平移动的速度。 以每秒像素为单位。

如果您不希望它在空中时改变速度,我们也可以这样做:

extends KinematicBody2D

export(NodePath) var player_path:NodePath = @"/root/World/Player"
export(float) var horizontal_speed:float = 100
export(float) var gravity:float = 100

onready var player:Node2D = get_node(player_path)
var _velocity:Vector2 = Vector2.ZERO

func _physics_process(delta:float) -> void:
    _velocity.y += gravity * delta
    _velocity = move_and_slide(_velocity,Vector2.UP)
    if is_on_floor():
        var direction_to_player = global_transform.origin.direction_to(player.global_transform.origin)
        _velocity.x = direction_to_player.x * horizontal_speed

注意我正在使用 global_transform.origin。您也可以使用 global_position。不要使用 transform.originposition,因为它们是相对于父节点的。如果父母不一样,你就会得到一个错误的方向。 *我倾向于使用变换,因为

还请注意,我在 is_on_floor 之后使用了 move_and_slide,因此我获得了更新后的值。我强烈鼓励这种模式:重力、移动和滑动、决策。

这不会跳或爬梯子或类似的东西。它也会卡在墙上。它与寻路或避障没有任何相似之处。因此,正如您想象的那样,根据您想要做什么,它可能会变得非常复杂。然而,它从那里成长。我对您想要赋予这些运动学体的行为知之甚少,除此之外,您希望它们使用 mode_and_slide 和重力传递给玩家,我不知道。因此,我无法进一步帮助您。