Godot:如何将 KinematicBody2D 节点从一个场景移动到另一个场景
Godot: How to move KinematicBody2D node from one scene to another
我想将我的 Player 节点 (KinematicBody2D) 从一个场景移动到另一个场景。我的代码成功移动了 Node2D 节点,但使用 KinematicBody2D 节点失败了。
我有两个具有以下结构的位置场景(继承自基本位置场景):
FirstLocation (inherits Location)
- YSort
- Player
在基础Location
场景中我有两种方法:
func add_player(player: Player):
get_node("YSort").add_child(player)
func remove_player() -> Player:
var player = get_node("YSort/Player")
get_node("YSort").remove_child(player)
return player
在 GameWorld
场景中,我将可能的位置存储在字典中,玩家的移动发生在 change_location() 函数中:
onready var _locations = {
Location.FOO: $CurrentLocation,
Location.BAR: load("res://locations/Bar.tscn").instance(),
}
onready var _current_location = $CurrentLocation
func change_location(location: int):
var player = _current_location.remove_player()
remove_child(_current_location)
_current_location = _locations[location]
add_child(_current_location)
_current_location.add_player(player)
- 位置切换有效
- 如果播放器是普通 Node2D,播放器的移动也有效。
但是当 Player 是 KinematicBody2D 时,游戏就会崩溃,没有提示我是什么导致了问题。
当我注释掉最后一行时,代码可以正常工作而不会崩溃:
_current_location.add_player(player)
...但是当然玩家不会被添加到另一个场景中。
- 我确认玩家确实已从场景中移除。
- 我测试了一个虚拟场景(它只包含 KinematicBody2D 作为根节点和一个简单的 Sprite 作为单个子节点)而不是我实际的更复杂的 Player 场景,以确保它与我可能拥有的任何其他代码无关我的播放器场景。
Node2D 作为 root 工作,KinematicBody2D 崩溃。 一定是侥幸。再次测试,现在两者都有效,所以我的 Player 对象中一定有不同。
- 我尝试将 Player 节点添加为 Location 节点的直接子节点(中间没有 YSort 节点)- 不,仍然崩溃。
- 我尝试设置播放器 before/after 的 position/global_position 将其添加到新场景 - 没有区别。
- 我能够创建新的 Player 场景实例并将其添加到新位置。
KinematicBody2D 中有什么阻止我将它从一个场景移动到另一个场景?
找到了解决方法,但不知道为什么有效。
我正在执行位置更改作为对 Area2D.body_entered
信号的响应。我触发了自己的信号“location_change”,然后在代码的另一部分调用了change_location()
函数来响应它。
在进行位置更改之前添加一个微小的超时(0.00000001 秒)解决了这个问题。但是我不知道为什么,我很确定添加超时不是解决这个问题的正确方法。
我无法想象情况。但是考虑到问题发生在移除和添加物理体时,并且涉及"body_entered"
,并且您找到的解决方案是添加超时…
听起来问题是在 Godot 仍在解析物理响应时移除了物理体。然后解决方案就是等到下一帧。
您可以等到下一个图形帧:
yield(get_tree(), "idle_frame")
或者直到下一个物理框架:
yield(get_tree(), "physics_frame")
这比一些任意的小超时要好。
或者,您也可以延迟信号连接。
如果您从 UI 进行连接,“将信号连接到方法”对话框中将有一个“高级”开关。启用“高级”切换将显示一些额外的内容,包括延迟连接。
如果您正在连接表单代码,您可以通过传递 CONNECT_DEFERRED
标志来完成同样的事情。
我想将我的 Player 节点 (KinematicBody2D) 从一个场景移动到另一个场景。我的代码成功移动了 Node2D 节点,但使用 KinematicBody2D 节点失败了。
我有两个具有以下结构的位置场景(继承自基本位置场景):
FirstLocation (inherits Location)
- YSort
- Player
在基础Location
场景中我有两种方法:
func add_player(player: Player):
get_node("YSort").add_child(player)
func remove_player() -> Player:
var player = get_node("YSort/Player")
get_node("YSort").remove_child(player)
return player
在 GameWorld
场景中,我将可能的位置存储在字典中,玩家的移动发生在 change_location() 函数中:
onready var _locations = {
Location.FOO: $CurrentLocation,
Location.BAR: load("res://locations/Bar.tscn").instance(),
}
onready var _current_location = $CurrentLocation
func change_location(location: int):
var player = _current_location.remove_player()
remove_child(_current_location)
_current_location = _locations[location]
add_child(_current_location)
_current_location.add_player(player)
- 位置切换有效
- 如果播放器是普通 Node2D,播放器的移动也有效。
但是当 Player 是 KinematicBody2D 时,游戏就会崩溃,没有提示我是什么导致了问题。
当我注释掉最后一行时,代码可以正常工作而不会崩溃:
_current_location.add_player(player)
...但是当然玩家不会被添加到另一个场景中。
- 我确认玩家确实已从场景中移除。
- 我测试了一个虚拟场景(它只包含 KinematicBody2D 作为根节点和一个简单的 Sprite 作为单个子节点)而不是我实际的更复杂的 Player 场景,以确保它与我可能拥有的任何其他代码无关我的播放器场景。
Node2D 作为 root 工作,KinematicBody2D 崩溃。一定是侥幸。再次测试,现在两者都有效,所以我的 Player 对象中一定有不同。 - 我尝试将 Player 节点添加为 Location 节点的直接子节点(中间没有 YSort 节点)- 不,仍然崩溃。
- 我尝试设置播放器 before/after 的 position/global_position 将其添加到新场景 - 没有区别。
- 我能够创建新的 Player 场景实例并将其添加到新位置。
KinematicBody2D 中有什么阻止我将它从一个场景移动到另一个场景?
找到了解决方法,但不知道为什么有效。
我正在执行位置更改作为对 Area2D.body_entered
信号的响应。我触发了自己的信号“location_change”,然后在代码的另一部分调用了change_location()
函数来响应它。
在进行位置更改之前添加一个微小的超时(0.00000001 秒)解决了这个问题。但是我不知道为什么,我很确定添加超时不是解决这个问题的正确方法。
我无法想象情况。但是考虑到问题发生在移除和添加物理体时,并且涉及"body_entered"
,并且您找到的解决方案是添加超时…
听起来问题是在 Godot 仍在解析物理响应时移除了物理体。然后解决方案就是等到下一帧。
您可以等到下一个图形帧:
yield(get_tree(), "idle_frame")
或者直到下一个物理框架:
yield(get_tree(), "physics_frame")
这比一些任意的小超时要好。
或者,您也可以延迟信号连接。
如果您从 UI 进行连接,“将信号连接到方法”对话框中将有一个“高级”开关。启用“高级”切换将显示一些额外的内容,包括延迟连接。
如果您正在连接表单代码,您可以通过传递 CONNECT_DEFERRED
标志来完成同样的事情。