Search code examples
game-developmentgdscript3d-modellinggodot4

Find Area node is collided is celling, floor or wall in godot4


I have a area node in godot4 which can scale up and down and also rotate. there are celling, floor and wall in scene, my area node place between them and can scale up, when this area got bigger can collide with other areas like floor, wall or celling. I want to know that area i collided is wall, floor or celling. I know there is characterbody node which has method that shows node which is collided is wall, floor or ceiling. but I want to use area node for both of them. how can I find node which is collided is wall, celling or floor? Thanks in advance.

this is my code: func my_raycast(myray:RayCast3D,myarea:Area3D): myray.global_position = center_pivot.global_position myray.enabled = true

myray.target_position = myarea.global_position - myray.global_position
if(myray.is_colliding()):
    if(myray.get_collider().name==myarea.name):
        #myray.enabled = false
        print("colided")
        
        var mynormal = myray.get_collision_normal()
        print(myray.get_collision_normal())
        
        if(mynormal.is_zero_approx()):
        mynormal = -myray.global_position.direction_to(myray.to_global(myray.target_position))
            
        var is_floor:bool = mynormal.angle_to(myarea.transform.basis.y/myarea.scale.y) <= PI/4
        var is_ceiling:bool = mynormal.angle_to(myarea.transform.basis.y/myarea.scale.y) <= PI/4
        var is_wall:bool = mynormal.angle_to(myarea.transform.basis.y/myarea.scale.y) <= PI/4

=============== never condition of is_zero_approx got true.

I used raycast for finding normal of node I collided but I don't have any idea, how to find answer? I don't want to use layer or tags on wall, floor and celling @Theorat


Solution

  • I'm not sure how do you decide where to aim a raycast, but we can come back to that.


    This is how you would mimic what character body does with a raycast:

    if raycast.is_colliding():
        var normal := raycast.get_collision_normal()
        var is_floor := normal.angle_to(up_direction) <= floor_max_angle
        var is_ceiling := (-normal).angle_to(up_direction) <= floor_max_angle
        var is_wall := not result.is_floor and not result.is_ceiling
    

    You, of course, need to define up_direction and floor_max_angle, just like with the actual character body. By default up_direction will be the UP constant, and floor_max_angle is 45º (PI/4).


    So where do you aim the raycast? Just going for the origin of the other object transform is not correct... The origin might be anywhere relative to the actual collision shape. Even aiming to the center of the collision shape might not be correct as the collision might happen off-center.

    If the goal is mimic the character body, you would be checking where it collides as it moves.

    So, I don't know if you want to try a shape cast that mimics the motion of your area, or something else. I'll link here another answer where I talk about checking the collisions from code, which might get you started on that.