ray-casting.rst 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. .. _doc_ray-casting:
  2. Ray-casting
  3. ===========
  4. Introduction
  5. ------------
  6. One of the most common tasks in game development is casting a ray (or
  7. custom shaped object) and checking what it hits. This enables complex
  8. behaviors, AI, etc. to take place. This tutorial will explain how to
  9. do this in 2D and 3D.
  10. Godot stores all the low level game information in servers, while the
  11. scene is just a frontend. As such, ray casting is generally a
  12. lower-level task. For simple raycasts, node such as
  13. :ref:`RayCast <class_RayCast>` and :ref:`RayCast2D <class_RayCast2D>`
  14. will work, as they will return every frame what the result of a raycast
  15. is.
  16. Many times, though, ray-casting needs to be a more interactive process
  17. so a way to do this by code must exist.
  18. Space
  19. -----
  20. In the physics world, Godot stores all the low level collision and
  21. physics information in a *space*. The current 2d space (for 2D Physics)
  22. can be obtained by accessing
  23. :ref:`CanvasItem.get_world_2d().space <class_CanvasItem_get_world_2d>`.
  24. For 3D, it's :ref:`Spatial.get_world().space <class_Spatial_get_world>`.
  25. The resulting space :ref:`RID <class_RID>` can be used in
  26. :ref:`PhysicsServer <class_PhysicsServer>` and
  27. :ref:`Physics2DServer <class_Physics2DServer>` respectively for 3D and 2D.
  28. Accessing space
  29. ---------------
  30. Godot physics runs by default in the same thread as game logic, but may
  31. be set to run on a separate thread to work more efficiently. Due to
  32. this, the only time accessing space is safe is during the
  33. :ref:`Node._physics_process() <class_Node__physics_process>`
  34. callback. Accessing it from outside this function may result in an error
  35. due to space being *locked*.
  36. To perform queries into physics space, the
  37. :ref:`Physics2DDirectSpaceState <class_Physics2DDirectSpaceState>`
  38. and :ref:`PhysicsDirectSpaceState <class_PhysicsDirectSpaceState>`
  39. must be used.
  40. Use the following code in 2D:
  41. ::
  42. func _physics_process(delta):
  43. var space_rid = get_world_2d().space
  44. var space_state = Physics2DServer.space_get_direct_state(space_rid)
  45. Or more directly:
  46. ::
  47. func _physics_process(delta):
  48. var space_state = get_world_2d().direct_space_state
  49. And in 3D:
  50. ::
  51. func _physics_process(delta):
  52. var space_state = get_world().direct_space_state
  53. Raycast query
  54. -------------
  55. For performing a 2D raycast query, the method
  56. :ref:`Physics2DDirectSpaceState.intersect_ray() <class_Physics2DDirectSpaceState_intersect_ray>`
  57. may be used. For example:
  58. ::
  59. func _physics_process(delta):
  60. var space_state = get_world().direct_space_state
  61. # use global coordinates, not local to node
  62. var result = space_state.intersect_ray(Vector2(0, 0), Vector2(50, 100))
  63. The result is a dictionary. If the ray didn't hit anything, the dictionary will
  64. be empty. If it did hit something it will contain collision information:
  65. ::
  66. if result:
  67. print("Hit at point: ", result.position)
  68. The ``result`` dictionary when a collision occurs contains the following
  69. data:
  70. ::
  71. {
  72. position: Vector2 # point in world space for collision
  73. normal: Vector2 # normal in world space for collision
  74. collider: Object # Object collided or null (if unassociated)
  75. collider_id: ObjectID # Object it collided against
  76. rid: RID # RID it collided against
  77. shape: int # shape index of collider
  78. metadata: Variant() # metadata of collider
  79. }
  80. The data is similar in 3D space, using Vector3 coordinates.
  81. Collision exceptions
  82. --------------------
  83. A common use case for ray casting is to enable a character to gather data
  84. about the world around it. One problem with this is that the same character
  85. has a collider, so the ray will only detect its parent's collider,
  86. as shown in the following image:
  87. .. image:: img/raycast_falsepositive.png
  88. To avoid self-intersection, the ``intersect_ray()`` function can take an
  89. optional third parameter which is an array of exceptions. This is an
  90. example of how to use it from a KinematicBody2D or any other
  91. collision object node:
  92. ::
  93. extends KinematicBody2D
  94. func _physics_process(delta):
  95. var space_state = get_world().direct_space_state
  96. var result = space_state.intersect_ray(global_position, enemy_position, [self])
  97. The exceptions array can contain objects or RIDs.
  98. Collision Mask
  99. --------------
  100. While the exceptions method works fine for excluding the parent body, it becomes
  101. very inconvenient if you need a large and/or dynamic list of exceptions. In
  102. this case, it is much more efficient to use the collision layer/mask system.
  103. The optional fourth argument for ``intersect_ray()`` is a collision mask. For
  104. example, to use same mask as the parent body, use the ``collision_mask``
  105. member variable:
  106. ::
  107. extends KinematicBody2D
  108. func _physics_process(delta):
  109. var space_state = get_world().direct_space_state
  110. var result = space_state.intersect_ray(global_position, enemy_position,
  111. [self], collision_mask)
  112. 3D ray casting from screen
  113. --------------------------
  114. Casting a ray from screen to 3D physics space is useful for object
  115. picking. There is not much of a need to do this because
  116. :ref:`CollisionObject <class_CollisionObject>`
  117. has an "input_event" signal that will let you know when it was clicked,
  118. but in case there is any desire to do it manually, here's how.
  119. To cast a ray from the screen, you need a :ref:`Camera <class_Camera>`
  120. node. A ``Camera`` can be in two projection modes: perspective and
  121. orthogonal. Because of this, both the ray origin and direction must be
  122. obtained. This is because ``origin`` changes in orthogonal mode, while
  123. ``normal`` changes in perspective mode:
  124. .. image:: img/raycast_projection.png
  125. To obtain it using a camera, the following code can be used:
  126. ::
  127. const ray_length = 1000
  128. func _input(event):
  129. if event is InputEventMouseButton and event.pressed and event.button_index == 1:
  130. var camera = $Camera
  131. var from = camera.project_ray_origin(event.position)
  132. var to = from + camera.project_ray_normal(event.position) * ray_length
  133. Remember that during ``_input()``, the space may be locked, so in practice
  134. this query should be run in ``_physics_process()``.