跳到主要内容

信号的用法

在本章节的内容中,我们将为大家介绍IdeaXR中信号的基本概念,使用方法,以及如何在IdeaXR中通过信号来触发一系列的动作,让内容看起来更加生动、有趣。

信号的概念

信号描述及作用

节点在发生某些事件时会发出信号,此功能无需在代码中硬连接它们就能让节点相互通信。使用信号允许场景中的一个物体对另一个物体的变化做出反应,而无需相互引用。使用信号可以限制耦合,并保持代码的灵活性。

例如,按钮在按下时会发出信号。您可以连接到此信号以运行代码以响应此事件,例如启动游戏或打开菜单。其他内置信号可以告诉您两个对象何时碰撞,角色或怪物何时进入给定区域等等。您还可以针对自己的内容量身定制新的信号。

备注

IdeaXR中的信号实现采用观察者模式,您可以通过以下「C语言中文网」连接了解更多关于观察者设计模式的内容。

http://c.biancheng.net/view/1390.html.

自定义信号

除了类似按钮的按下事件,两个对象的碰撞反馈,IdeaXR还支持自定义信号,以满足用户深度的使用。在IdeaXR的脚本中,可以通过signal关键字来自定义信号,如:

signal room_prepared

定义好信号后,就可以在脚本里通过emit_signal来触发信号

emit_signal("room_prepared")

关于自定义信号,我们将在后续的章节中进行深入的介绍。

在IdeaXR中使用信号

在这部分内容中,我们将通过一个最简单的示例,来展示如何通过按钮按下的信号来控制场景中几何对象的显示和隐藏操作。

为了使用信号,我们首先要准备一个场景文件,如果您在此之前已经有了IdeaXR的工程文件,那么您可以直接跳过这一步骤。首先,请通过IdeaXR项目管理器基于基础场景模板项目创建一个名为SignalStudy的工程。

创建好的项目,如下图所示

然后,我们通过场景管理器的+号来创建一个Button节点。我们可以在创建面板最上方的节点过滤器中输入button来快速定位到我们想要创建的节点。

按钮创建完成后,我们可以通过Button组件周围的控制点调整下按钮的尺寸,并将按钮的文本修改为显隐几何体

至此,我们便初具一个演示信号使用的demo场景。接下来,我们将通过在编辑器中连接信号和在脚本中连接信号的方式,来实现通过按钮实现场景中几何体显隐的控制。

在编辑器中连接信号

1. 为接收信号的节点添加脚本

在这里,我们希望将按钮的pressed信号连接到我们的空间节点,并且我们想要调用一个新函数来显示和隐藏场景中的几何体。我们需要将脚本附加到空间节点节点,默认情况下,空间节点是没有挂载脚本的,我们可以选中该节点,然后右键选择添加脚本,在弹出的面板中选择IVRScript脚本。

tip

可视化脚本也支持连接信号,具体用法详见交互编辑器-信号章节。

extends Spatial

# Declare member variables here. Examples:
# var a = 2
# var b = "text"

# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.

# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass

2. 通过节点面板连接信号

首先选择按钮节点,然后在编辑器的右侧,单击属性面板标签页旁边名为节点的选项卡。停靠栏显示所选节点上可用的信号列表。双击pressed信号或选中pressed信号后,点击右下角的连接信号...按钮,打开节点连接窗口。

在连接信号面板,您可以将信号连接到空间节点节点。节点需要一个接收器方法,当按钮发出信号时,IdeaXR将调用该函数。编辑器会为您生成一个。按照惯例,我们将这些回调方法命名为_on_节点名_信号名。在这里,它将是_on_按钮_pressed

IdeaXR将会在空间节点挂载的脚本上,自动添加以下内容

func _on_按钮_pressed():
pass # Replace with function body.

以上,我们就在编辑器中完成了按钮的信号与事件的连接,现在我们运行场景,点击按钮并不会发现有什么效果。那是因为,信号对应的事件处理函数并没有具体的执行逻辑,而是直接pass,所以并不会有任何效果产生。

为了实现点击按钮时,切换几何体的显隐状态,我们可以在_on_按钮_pressed函数中,增加以下代码

func _on_按钮_pressed():
# 判断几何体的可见性,并根据结果进行相应的处理
if($几何体.visible):
$几何体.hide()
else:
$几何体.show()
提示

在脚本中访问节点树中的节点时,其路径是相对于挂载当前脚本的节点而言的。如,上面的代码片段,为了访问空间节点下的几何节点,可以通过$几何体来获取。

运行该场景,然后点击按钮,就可以看到几何体显示或消失。程序运行时的效果如下图所示。

动态连接信号

除了上面通过编辑器来实现信号与事件处理函数的连接,我们也可以通过代码来连接信号。这在脚本中创建节点或实例化场景时时必须的。接下来的讲解,我们依然使用上面的案例。在开始之前,我们需要先在编辑器中解除之前按钮的信号连接。

在选中按钮节点的状态下,切换至节点标签页。我们可以看到在pressed信号下,已经存在了_on_按钮_pressed的事件连接。选中该信号,右键删除,即可恢复默认的初始状态。

提示

虽然信号的绑定关系被删除,但是在脚本中增加的处理函数,依然存在,一般情况下,解除绑定后如不再需要对应的处理,应将代码中相应的函数删除。为了便于后面内容的讲解,脚本里的函数继续保留。

通过脚本动态连接

因为信号的连接,我们只需要连接一次,该绑定状态将一直持续存在,直到我们解除绑定或资源被销毁,故应在类似初始化的函数中进行绑定。在空间节点上增加脚本的时候,IdeaXR默认会帮我们新建一个func _ready()的函数,该函数只在执行的时候运行一次。

IdeaXR中,可以通过connect关键字将信号和与之对应的触发事件关联起来。

# Called when the node enters the scene tree for the first time.
func _ready():
$按钮.connect("pressed", self, "_on_按钮_pressed")

func _on_按钮_pressed():
# 判断几何体的可见性,并根据结果进行相应的处理
if($几何体.visible):
$几何体.hide()
else:
$几何体.show()

上述代码即完成了与前一部分在编辑器中实现信号连接同样的效果。其中,connect函数的第一个参数为按钮的信号名,此处为按钮的按下事件。第二个参数为连接到的target_instance实例,最后一个参数则为事件触发函数。

自定义信号

前面,我们有提到,IdeaXR支持自定义信号。例如,假设您希望在用户的剩余操作时长为零时通过屏幕显示游戏结束。为此,当他们的剩余操作时长达到0时,我们可以定义一个名为task_over的信号。


extends Spatial
signal task_over
var time_remains = 20

# 在应用开始后,任务执行过程中的时间扣除函数
func take_task(amount):
time_remains -= amount
if time_remains <= 0:
emit_signal("task_over")

上述代码,很清楚地表达了任务在执行过程中的时间消耗,以及到达指定时间后,触发自定义信号的过程。

IdeaXR信号小结

IdeaXR中,任何节点都会在发生特定事件时发出信号,例如按下按钮、两个物体发生碰撞时。其他节点可以连接到单个信号并对所选事件做出反应。在虚拟现实应用或游戏内容开发中,信号有很多用途。有了信号,我们可以对进入或退出虚拟世界的节点、碰撞、角色进入或离开某个区域、界面元素的大小变化等等做出反应。

通过本节内容,我们对信号有了初步的了解。想要学习更多关于信号的知识,请继续后续章节的学习吧。