目录
在我的[手把手带你Godo游戏开发]第一弹FlappyBird教程中,有这样一段代码
BUG版本:
# Bird.gd
extends RigidBody2D
func _ready():
connect("body_entered",self,"on_body_entered")
func _physics_process(delta):
if Input.is_mouse_button_pressed(1):
linear_velocity = Vector2.UP*500
func on_body_entered(_body):
if _body is StaticBody2D:
set_physics_process(false)
set_contact_monitor(false)
结果运行时报了错
E 0:00:04.970 set_contact_monitor: Can't disable contact monitoring during in/out callback. Use call_deferred("set_contact_monitor", false) instead.
<C ++错误> Condition "contact_monitor->locked" is true.
<C++源程序> scene/2d/physics_body_2d.cpp:894 @ set_contact_monitor()
<栈追踪> Bird.gd:22 @ on_body_entered()
其实错误提示已经描述得很清晰
因为Godot Engine的物理引擎使用了多线程来提高效率,因此发生碰撞时,contact_monitor
会被线程锁定,无法直接通过set_contact_monitor
来关闭,使用call_deferred
延迟调用set_contact_monitor
.
call_deferred方法
原型
void call_deferred ( StringName method, … ) vararg
说明
-
call_deferred
是Object
类的方法。 - 第一个参数
StringName method
是方法名,后面是可变数量参数,对应着被调用方法的参数。 -
call_deferred
的作用是延迟到所属对象的空闲(Idle)状态时再调用StringName method
,这是一个非常方便好用的功能!
修复版本:
# Bird.gd
extends RigidBody2D
func _ready():
connect("body_entered",self,"on_body_entered")
func _physics_process(delta):
if Input.is_mouse_button_pressed(1):
linear_velocity = Vector2.UP*500
func on_body_entered(_body):
if _body is StaticBody2D:
call_deferred("set_physics_process",false)#停用_physics_process(delta)
call_deferred("set_contact_monitor",false)#关闭碰撞检测
说明: 严格来讲
set_physics_process
并没有必要用call_deferred
来调用。