原理
电脑的鼠标是在屏幕的2D坐标上运动的,而我们要获取的是3D世界中的一个三维坐标,在游戏引擎中的实现原理如下:
- 先获取鼠标在屏幕上的2D坐标。
- 结合摄像机平面计算出这个点在3D世界中的坐标。
- 从这个3D坐标沿着摄像机的视角发射一条射线,让这个射线和3D世界中的对象发生碰撞。
- 这样,如果发生了碰撞,我们就可以获取最先和射线碰撞的物体以及发生碰撞的点坐标。
在Godot中可以这样实现,把下面的代码放在摄像机上
extends Cameraconst ray_length : int = 1000func _input(event):if event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT:var from:Vector3 = project_ray_origin(event.position)var to:Vector3 = from + project_ray_normal(event.position) * ray_lengthvar state:PhysicsDirectSpaceState = get_world().direct_space_statevar result:Dictionary = state.intersect_ray(from,to)if result:get_tree().call_group("LMB_LISTENER","on_LMB_down",result.position)
注意
- 上文中的
state.intersect_ray(from,to)
射线需要和CollisionShape
或者Area
(默认只有CollisionShape
)发生碰撞才会有返回值,所以,必须给所有有效区域都加上CollisionShape
或者Area
- 这个实现中使用了Godot非常好用的
Group
机制,想要接收鼠标位置的观察者
们,只需要在_ready
中通过add_to_group("LMB_LISTENER")
把自己加入到"LMB_LISTENER"
组中,然后再实现一下func on_LMB_down(pos : Vector3)
方法就可以了