我正在使用 Godot 4.0,并且遇到了 TextureProgressBar 的问题。为了重现此问题,请创建一个新项目,创建一个新场景作为 Node2D,并添加子 Timer 和 CanvasLayer。然后为 CanvasLayer 提供它自己的子级,即 TextureProgressBar。在Node2D中添加一个gdscript文件,并将定时器的timeout()信号连接到它(我将定时器的名称更改为StartTimer,将CanvasLayer更改为Loading Screen,将TextureProgressBar更改为Loading Bar,这就是func调用名称不同的原因在提供的代码中)。然后将脚本文件中的代码替换为:
extends Node2D
func _ready():
get_node("Loading Screen/Loading Bar").position = Vector2(200, 360)
get_node("Loading Screen/Loading Bar").set_value(1)
func start_world_creation():
start_progress_bar()
func start_progress_bar():
for x in 100:
for y in 100:
for time_waster in range(20000):
time_waster += 300
get_node("Loading Screen/Loading Bar").value += 1
print(get_node("Loading Screen/Loading Bar").value)
func _process(delta):
pass
func _on_start_timer_timeout():
start_world_creation()
最后,将下面的图像分配到TextureProgressBar各自的位置:
由于某种原因,TextureProgressBar 在其值达到 100 之前不会更新。这是为什么,我该如何修复它?根据文档,它应该随着每个整数值的增加而更新,因为 TextureProgressBar 的步长值设置为 1,并且 max_value 为 100。
因此发出
Timer
的信号,并且此代码将在下一帧之前运行:
func _on_start_timer_timeout():
start_world_creation()
正在调用此代码,该代码将在下一帧之前完成:
func start_world_creation():
start_progress_bar()
正在调用此代码,该代码将在下一帧之前完成:
func start_progress_bar():
for x in 100:
for y in 100:
for time_waster in range(20000):
time_waster += 300
get_node("Loading Screen/Loading Bar").value += 1
print(get_node("Loading Screen/Loading Bar").value)
因此,当 Godot 最终到达下一帧时,
value
的 TextureProgressBar
位于 100.0
,这也是默认的 max_value
,所以你会看到它已满。
希望您能看到这个问题:
time_waster
等人。使线程保持忙碌,因此 Godot 无法做其他事情。 在这种情况下,使用 set_deferred
或 call_deferred
对您没有帮助。
更简单的解决方案是
await
一个框架:
func start_progress_bar():
for x in 100:
for y in 100:
for time_waster in range(20000):
time_waster += 300
get_node("Loading Screen/Loading Bar").value += 1
print(get_node("Loading Screen/Loading Bar").value)
await get_tree().process_frame
当执行到
await
时,Godot会保存在原来的位置,并在发出指定信号(本例中为get_tree().process_frame
)后继续。
您可以做的另一件事是在另一个
Thread
中运行代码。 在这种情况下,您可以使用 set_deferred
或 call_deferred
来操作 UI。
如果
time_waster
等人。代码是某些异步操作的替代,您可能还想寻找适当的信号(或创建一个信号),这样您就可以await
直到异步操作完成。
警告:使用
await
有缺点:无法取消或断开连接。
因此:
object
被释放,并且发出信号,则出现运行时错误。如果遇到这种情况,请通过将
Callable
延续(可以是匿名方法,又名“lambda”)连接到信号来重构代码...当对象被释放时,Godot 会断开它。
如果您需要检查
Node
是否即将被queue_free
释放,您可以检查is_queued_for_deletion
。如果您需要检查是否有对已释放的 Node
的引用,请使用 is_instance_valid
。如果您需要在释放 Object
之前执行某些操作,请让它覆盖 _notification
并对 NOTIFICATION_PREDELETE
作出反应。