Godot Engine:用call_deferred线程安全地调用一个方法

在我的[手把手带你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_deferredObject类的方法。
  • 第一个参数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来调用。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开发游戏的老王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值