godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.92k stars 20.16k forks source link

`RayCast3D` cannot detect collision with CSGs in `_ready()` even with `force_raycast_update()` #96025

Open ItzCog opened 3 weeks ago

ItzCog commented 3 weeks ago

Tested versions

v4.3.stable.mono.official [77dcf97d8]

System information

Godot v4.3.stable.mono - macOS 14.5.0 - Vulkan (Forward+) - integrated Apple M1 - Apple M1 (8 Threads)

Issue description

RayCast3D cannot properly detect collision with a CSG shape when the collision checking is performed in _ready(), even when force_raycast_update() is used. Method is_colliding() always returns false, despite that "Debug > Visible Collision Shapes" would indicate there is a collision and the same checking performed in _physics_process() behaves correctly.

This issue seems similar to another one previously mentioned but there it was a RayCast3D colliding with a StaticBody3D and using a force_raycast_update() would make it work properly. Here it seems to have no effect.

Steps to reproduce

  1. Make a 3D scene.
  2. Add one of the CSG shapes and set use_collision to true.
  3. Add a RayCast3D and position it so that it starts off colliding with the CSG shape.
  4. Add a script to the RayCast3D to perform some collision checking in _ready(). This is what I used:
    
    extends RayCast3D

func _ready() -> void: force_raycast_update() print("is_colliding: " + str(is_colliding())) print("get_collider: " + str(get_collider()))

5. Run the game. The script will tell you that no collision is taking place. The output result for the script above is the following:

is_colliding: false get_collider: <Object#null>



### Minimal reproduction project (MRP)

[raycast.zip](https://github.com/user-attachments/files/16735530/raycast.zip)
smix8 commented 3 weeks ago

Use call_deferred() or await the physics tick instead of using a _ready() function.

A _ready() is "this node has joined the SceneTree successfully" and not "every single part of the setup of this node was done".

Plenty of nodes involve server setups with sync queues, those are never "fully ready" in a _ready() function call.

A CSGShape needs to be build first and then synced with the server. In the majority of cases CSG shapes involve multiple nodes under a CSG combination so CSG nodes need to wait for all other SceneTree nodes that may take all part in the same CSG operation. Even if the CSG node would not need to wait for other nodes its freshly build collision shape would still be in the physics sync queue and only available after the next physics sync.

ItzCog commented 3 weeks ago

Thanks for the explanation.

I think it would be nice to have this bit mentioned in RayCast3D documentation because it can definitely be somewhat confusing for the less experienced users.