无效的获取索引'1'(基于:'Array')GODOT路径查找
Invalid get index '1' (on base: 'Array') GODOT path finding
我正在尝试制作一只跟随附加到角色的 Position2D 节点的鸟。(Position2D 节点位于名为 birdpos 的组中)当我 运行 鸟出现在屏幕上时(screendetector) 它转到 Position2D 节点。然而,一旦它到达目的地,它就会给我错误消息“无效的获取索引'1'(基于:'Array')。” (当它到达位置时我也会抖动)我相信这是一个简单的修复,这是我的代码
extends KinematicBody2D
export(int) var SPEED: int = 100
var velocity: Vector2 = Vector2.ZERO
var path: Array = []
var levelNavigation: Navigation2D = null
var birdpos = null
onready var line2d = $Line2D #shows pathing
func _ready():
var tree = get_tree()
$flyingsprite1/AnimationPlayer.play("flying")
if tree.has_group("LevelNavigation"):
levelNavigation = tree.get_nodes_in_group("LevelNavigation")[0]
func move():
velocity = move_and_slide(velocity)
func _on_screenchecker_area_entered(area):
$Timer.start()
print("ligma")
yield(get_tree(), "idle_frame")
var tree = get_tree()
if tree.has_group("LevelNavigation"): #navigation node
levelNavigation = tree.get_nodes_in_group("LevelNavigation")[0]
if tree.has_group("birdpos"): #Position2D that is attached to player
birdpos = tree.get_nodes_in_group("birdpos")[0]
func _on_screenchecker_area_exited(area):
print("liga")
$Timer.stop()
var birdpos = null
var levelNavigation: Navigation2D = null
func _on_Timer_timeout():
line2d.global_position = Vector2.ZERO
if birdpos and levelNavigation:
generate_path()
func _physics_process(delta):
if Global.player.facing_right == true:
$flyingsprite1.scale.x = -1
else:
$flyingsprite1.scale.x = 1
if birdpos and levelNavigation:
navigate()
move()
func generate_path():
if levelNavigation != null and birdpos != null:
path = levelNavigation.get_simple_path(global_position, birdpos.global_position, false)
line2d.points = path
func navigate():
if path.size() > 0:
velocity = global_position.direction_to(path[1]) * SPEED
if global_position == path[0]:
path.pop_front()
编辑:更新代码
extends KinematicBody2D
export(int) var SPEED: int = 200
var velocity: Vector2 = Vector2.ZERO
var path: Array = []
var levelNavigation: Navigation2D = null
var birdpos = null
onready var line2d = $Line2D
func _ready():
# speed is distance over time
var tree = get_tree()
$flyingsprite1/AnimationPlayer.play("flying")
#if tree.has_group("Player"):
#player = tree.get_nodes_in_group("Player")[0]
func _on_screenchecker_area_exited(area):
$Timer.stop()
var birdpos = null
var levelNavigation: Navigation2D = null
func _on_Timer_timeout():
line2d.global_position = Vector2.ZERO
if birdpos and levelNavigation:
generate_path()
func _physics_process(delta):
if path.size() == 0:
return
var levelNavigation: Navigation2D = null
var birdpos = null
var next := global_position.move_toward(path[0], SPEED * delta)
var displacement := next - global_position
# And divide by it delta to get velocity:
move_and_slide(displacement/delta)
if Global.player.facing_right == true:
$flyingsprite1.scale.x = -1
else:
$flyingsprite1.scale.x = 1
if birdpos and levelNavigation:
navigate()
move()
func _input(event):
if Input.is_key_pressed(KEY_Q):
var tree = get_tree()
func _on_screenchecker_area_entered(area):
$Timer.start()
yield(get_tree(), "idle_frame")
var tree = get_tree()
if tree.has_group("LevelNavigation"):
levelNavigation = tree.get_nodes_in_group("LevelNavigation")[0]
if tree.has_group("birdpos"):
birdpos = tree.get_nodes_in_group("birdpos")[0]
func generate_path():
if levelNavigation != null and birdpos != null:
if is_instance_valid(birdpos):
path = levelNavigation.get_simple_path(global_position, birdpos.global_position, false)
line2d.points = path
func navigate():
if path.size() > 1:
velocity = global_position.direction_to(path[1]) * SPEED
if path.size() == 0:
path.pop_front()
func move():
if path.size() == 0:
return
velocity = move_and_slide(velocity)
错误
在此代码中:
if path.size() > 0:
velocity = global_position.direction_to(path[1]) * SPEED
if global_position == path[0]:
path.pop_front()
你检查 path
与 path.size() > 0
的得分是否超过 0。也就是说,您正在检查 path
是否至少有 1 个点。
但要访问path[1]
,路径必须至少有2个点。
因此,如果path
刚好有1点,它将通过检查path.size() > 0
,而在读取path[1]
时失败。
我不知道路径什么时候正好有一个点。 没有记录这是如何发生的,这可能是导航的问题,甚至可能是 Godot 中的错误。但是,据我所知,它正在发生你.
大概您想要达到 path[0]
而不是 path[1]
,因为这是您要检查的移除点数。
如果您确实想要 path[1]
,则检查路径是否至少有 2 个点 path.size() > 1
(或 path.size() >= 2
,如果您愿意)。
抖动
我在这里假设 path[0]
是目标。
我认为是三件事:
你不能相信向量相等
向量相等归结为分量相等。这是浮动平等。因此 Vector 相等性具有 float 相等性的所有问题。
因此,要与您当前的目标进行比较,请使用 is_equal_approx
。例如 global_position.is_equal_approx(path[0])
.
达到目标就不想动了
这很简单:如果 path
中没有更多点,请不要移动。也就是说,你可以在 move
:
的开头添加这个
if path.size() == 0:
return
如果你的代码在_physics_process
而不是move
,记得检查那里。
你不想超调
因此,move_and_slide
将根据物理帧之间的时间 (delta
) 尽可能多地移动对象。但这可能超出了实现目标的必要性。因此,它很可能会超过目标。结果,下一个物理框架它必须向相反的方向移动,并再次超调,等等……抖动!
我给你三个解决方案:
不要使用 move_and_slide
(注意您将放弃物理碰撞):
# you can use move_toward
global_position = global_position.move_toward(path[0], SPEED * delta)
让我们保持move_and_slide
,但计算我们想要的位移。
# you can use move_toward
var next := global_position.move_toward(path[0], SPEED * delta)
# Then compute the displacement
var displacement := next - global_position
# And divide by it delta to get velocity:
move_and_slide(displacement/delta)
再次使用move_and_slide
,但这次我们计算出不超过的最大速度:
# speed is distance over time
var max_speed := global_position.distance_to(path[0])/delta
# And we clamp!
move_and_slide(velocity.clamped(max_speed))
对于使用 delta
的代码版本,您可以将代码放在 _physics_process
中,或者将 delta
传递给 move
作为一个参数。也不要忘记检查前面提到的 path.size()
。
附录 如果你使用 path[0]
作为目标,但它等于当前位置,你将获得几乎没有速度,并且不得不浪费一个物理框架.考虑这个重写:
if path.size() > 0 and global_position.is_equal_approx(path[0]):
path.pop_front()
if path.size() > 0:
velocity = global_position.direction_to(path[0]) * SPEED
我正在尝试制作一只跟随附加到角色的 Position2D 节点的鸟。(Position2D 节点位于名为 birdpos 的组中)当我 运行 鸟出现在屏幕上时(screendetector) 它转到 Position2D 节点。然而,一旦它到达目的地,它就会给我错误消息“无效的获取索引'1'(基于:'Array')。” (当它到达位置时我也会抖动)我相信这是一个简单的修复,这是我的代码
extends KinematicBody2D
export(int) var SPEED: int = 100
var velocity: Vector2 = Vector2.ZERO
var path: Array = []
var levelNavigation: Navigation2D = null
var birdpos = null
onready var line2d = $Line2D #shows pathing
func _ready():
var tree = get_tree()
$flyingsprite1/AnimationPlayer.play("flying")
if tree.has_group("LevelNavigation"):
levelNavigation = tree.get_nodes_in_group("LevelNavigation")[0]
func move():
velocity = move_and_slide(velocity)
func _on_screenchecker_area_entered(area):
$Timer.start()
print("ligma")
yield(get_tree(), "idle_frame")
var tree = get_tree()
if tree.has_group("LevelNavigation"): #navigation node
levelNavigation = tree.get_nodes_in_group("LevelNavigation")[0]
if tree.has_group("birdpos"): #Position2D that is attached to player
birdpos = tree.get_nodes_in_group("birdpos")[0]
func _on_screenchecker_area_exited(area):
print("liga")
$Timer.stop()
var birdpos = null
var levelNavigation: Navigation2D = null
func _on_Timer_timeout():
line2d.global_position = Vector2.ZERO
if birdpos and levelNavigation:
generate_path()
func _physics_process(delta):
if Global.player.facing_right == true:
$flyingsprite1.scale.x = -1
else:
$flyingsprite1.scale.x = 1
if birdpos and levelNavigation:
navigate()
move()
func generate_path():
if levelNavigation != null and birdpos != null:
path = levelNavigation.get_simple_path(global_position, birdpos.global_position, false)
line2d.points = path
func navigate():
if path.size() > 0:
velocity = global_position.direction_to(path[1]) * SPEED
if global_position == path[0]:
path.pop_front()
编辑:更新代码
extends KinematicBody2D
export(int) var SPEED: int = 200
var velocity: Vector2 = Vector2.ZERO
var path: Array = []
var levelNavigation: Navigation2D = null
var birdpos = null
onready var line2d = $Line2D
func _ready():
# speed is distance over time
var tree = get_tree()
$flyingsprite1/AnimationPlayer.play("flying")
#if tree.has_group("Player"):
#player = tree.get_nodes_in_group("Player")[0]
func _on_screenchecker_area_exited(area):
$Timer.stop()
var birdpos = null
var levelNavigation: Navigation2D = null
func _on_Timer_timeout():
line2d.global_position = Vector2.ZERO
if birdpos and levelNavigation:
generate_path()
func _physics_process(delta):
if path.size() == 0:
return
var levelNavigation: Navigation2D = null
var birdpos = null
var next := global_position.move_toward(path[0], SPEED * delta)
var displacement := next - global_position
# And divide by it delta to get velocity:
move_and_slide(displacement/delta)
if Global.player.facing_right == true:
$flyingsprite1.scale.x = -1
else:
$flyingsprite1.scale.x = 1
if birdpos and levelNavigation:
navigate()
move()
func _input(event):
if Input.is_key_pressed(KEY_Q):
var tree = get_tree()
func _on_screenchecker_area_entered(area):
$Timer.start()
yield(get_tree(), "idle_frame")
var tree = get_tree()
if tree.has_group("LevelNavigation"):
levelNavigation = tree.get_nodes_in_group("LevelNavigation")[0]
if tree.has_group("birdpos"):
birdpos = tree.get_nodes_in_group("birdpos")[0]
func generate_path():
if levelNavigation != null and birdpos != null:
if is_instance_valid(birdpos):
path = levelNavigation.get_simple_path(global_position, birdpos.global_position, false)
line2d.points = path
func navigate():
if path.size() > 1:
velocity = global_position.direction_to(path[1]) * SPEED
if path.size() == 0:
path.pop_front()
func move():
if path.size() == 0:
return
velocity = move_and_slide(velocity)
错误
在此代码中:
if path.size() > 0:
velocity = global_position.direction_to(path[1]) * SPEED
if global_position == path[0]:
path.pop_front()
你检查 path
与 path.size() > 0
的得分是否超过 0。也就是说,您正在检查 path
是否至少有 1 个点。
但要访问path[1]
,路径必须至少有2个点。
因此,如果path
刚好有1点,它将通过检查path.size() > 0
,而在读取path[1]
时失败。
我不知道路径什么时候正好有一个点。 没有记录这是如何发生的,这可能是导航的问题,甚至可能是 Godot 中的错误。但是,据我所知,它正在发生你.
大概您想要达到 path[0]
而不是 path[1]
,因为这是您要检查的移除点数。
如果您确实想要 path[1]
,则检查路径是否至少有 2 个点 path.size() > 1
(或 path.size() >= 2
,如果您愿意)。
抖动
我在这里假设 path[0]
是目标。
我认为是三件事:
你不能相信向量相等
向量相等归结为分量相等。这是浮动平等。因此 Vector 相等性具有 float 相等性的所有问题。
因此,要与您当前的目标进行比较,请使用
is_equal_approx
。例如global_position.is_equal_approx(path[0])
.达到目标就不想动了
这很简单:如果
的开头添加这个path
中没有更多点,请不要移动。也就是说,你可以在move
:if path.size() == 0: return
如果你的代码在
_physics_process
而不是move
,记得检查那里。你不想超调
因此,
move_and_slide
将根据物理帧之间的时间 (delta
) 尽可能多地移动对象。但这可能超出了实现目标的必要性。因此,它很可能会超过目标。结果,下一个物理框架它必须向相反的方向移动,并再次超调,等等……抖动!我给你三个解决方案:
不要使用
move_and_slide
(注意您将放弃物理碰撞):# you can use move_toward global_position = global_position.move_toward(path[0], SPEED * delta)
让我们保持
move_and_slide
,但计算我们想要的位移。# you can use move_toward var next := global_position.move_toward(path[0], SPEED * delta) # Then compute the displacement var displacement := next - global_position # And divide by it delta to get velocity: move_and_slide(displacement/delta)
再次使用
move_and_slide
,但这次我们计算出不超过的最大速度:# speed is distance over time var max_speed := global_position.distance_to(path[0])/delta # And we clamp! move_and_slide(velocity.clamped(max_speed))
对于使用
delta
的代码版本,您可以将代码放在_physics_process
中,或者将delta
传递给move
作为一个参数。也不要忘记检查前面提到的path.size()
。
附录 如果你使用 path[0]
作为目标,但它等于当前位置,你将获得几乎没有速度,并且不得不浪费一个物理框架.考虑这个重写:
if path.size() > 0 and global_position.is_equal_approx(path[0]):
path.pop_front()
if path.size() > 0:
velocity = global_position.direction_to(path[0]) * SPEED