场景4—动态添加节点
概述
这个案例实现了一个点击屏幕后发射一个小球,小球会在一定时间后自动销毁的效果,完整的项目介绍请见应用教程。
场景准备
创建一个空场景,在场景中新建一个网格实例,在属性中选择“网格” -> “新建Sphere Mesh”,生成一个球体的网格实例,将缩放设为”0.2, 0.2, 0.2“
点击球体节点,使用工具栏左上角的“一键转换为刚体”
调整生成的刚体节点的属性,将质量调整为0.02
保存场景,命名为”球体.scene“
创建一个3D场景,命名为”动态创建节点.scene“(本案例添加了几个靶子作为交互的刚体,你可以在该场景文件夹中找到这些素材)
脚本实现
动态创建节点.is
在动态创建节点场景的根节点创建一个”动态创建节点脚本.is“,实现以下功能:
1. 在鼠标点击位置生成球体
每次点击时,首先通过相机的project_position
方法将鼠标点击的屏幕坐标投影到3D空间,得到球体发射的位置。这里使用get_tree().get_root().get_camera()
获取场景中正在使用的相机,也可以直接使用get_node
获取相机节点。
然后需要生成一个新的球体实例,使用duplicate
方法复制得到一个新的球体,将新的球体通过add_child
添加到根节点下,然后将其世界坐标设置为之前获取的位置。
func _input(event):
#当输入事件是鼠标按键左键且是按下状态时
if event is InputEventMouseButton and event.button_index == 1 and event.is_pressed():
var camera = get_tree().get_root().get_camera() #获取当前相机
var position = camera.project_position(event.position, 1) #根据点击所在屏幕位置生成投影到3D位置
var sphere = load("res://场景/场景4/球体.scene").instance() #加载球体场景
add_child(sphere) #添加球体
sphere.global_transform.origin = position #设置球体位置
var direction = camera.project_ray_normal(event.position) #获取垂直于相机屏幕的一个法线向量
info
通过load
方法获取文件中保存的球体场景,场景以PackedScene
类型存储,无法直接将其加入到场景树中,需要通过instance
方法将其转换为可以添加到场景中的Node
类型。
运行场景,可以看到点击屏幕后小球从点击位置掉落的效果:
2. 球体向前发射
球体是一个刚体类型,add_central_force
方法可以为其施加一个力,使其产生加速度。
力的方向垂直于相机屏幕朝前,这个方向可以通过相机的project_ray_normal
方法获取。
最后,将球体的质量设为0.02,使力的作用效果更加明显(也可以通过增加力的大小实现)。
direction = camera.project_ray_normal(event.position) #获取垂直于相机屏幕的一个法线向量
sphere.mass = 0.2 #设置刚体质量
sphere.add_central_force(750*direction) #施加一个力,产生加速度
运行场景,此时小球有发射的效果:
球体.is
在球体.scene的根节点创建一个”球体.is“脚本。
现在每次点击都会生成一个球体的刚体,在球体数量过多时可能会产生性能问题。通过queue_free
方法实现球体节点的销毁,在球体的脚本上添加以下内容:
var DESTORY_TIME = 3 #自动销毁等待的时间,单位为秒
var time = 0 #节点创建后经历的时间
func _physics_process(delta):
time += delta
if time >= DESTORY_TIME:
queue_free() #销毁节点
运行场景,所有发射出的小球会在三秒后自动消失。