Search code examples
gdscript

Problem accessing a node from a class [GDScript]


I encountered some difficulties while studying Godot.

I'm trying to add a shotgun class (Shotgun.gd). I have a function in the class that creates several RayCasts, a function that checks what they encounter and a function that calls these functions one by one. If I call these functions from the class where they are declared in the _process() function, everything works fine, but if I call these functions in another script, like Player.gd, it finds nothing when checking for RayCasts.

P.S Sorry for the sloppy translation, English is not my native language

Part of the code from the shotgun class (Shotgun.gd)

# Gen RayCast-ы
func gen_raycasts(player):
    # Очистка списка
    raycasts.clear()
    var temp
    
    for number in PELLETS_COUNT:
        # Создание RayCast
        temp = RayCast.new()
        
        # Установка настроек
        temp.set_cast_to(Vector3(LENGHT, 0, 0))
        temp.set_enabled(true)
        
        # Добавляет RayCast на сцену
        player.add_child(temp)
        
        # Установка положения
        temp.transform.basis = Basis(Vector3(-0, 0, 0.1), Vector3(-0, 0, 0.1), Vector3(0.1, 0, -0))
        temp.global_translate(Vector3(0, 1.65, 0))
        temp.set_scale(Vector3(0.1, 0.1, -0.1))
        
        # Рандомный разброс дробовика
        randomize()
        temp.rotate_y(deg2rad((-50 + randi() % 100) / 10))
        temp.rotate_x(deg2rad((-50 + randi() % 100) / 10))
        raycasts.append(temp)
        
    #print(raycasts)
        
# Check Rayasts
func chech_raycasts():
    in_raycast.clear()
    for number in PELLETS_COUNT:
        in_raycast.append(raycasts[number].get_collider())
        #print(raycasts[number].is_enabled())
        
    print(in_raycast)

Godot tree picture

Call from func _process()

Call from Player.gd


Solution

  • I'll venture to say that it is probably correct they collide with nothing.

    Enable "Visible Collision Shapes" in the "Debug" menu, so Godot shows colliders in runtime (including enabled RayCasts), and check they are being positioned correctly.


    I can think of a couple possible problems:

    • You are adding the RayCast before positioning it. This is not always a problem, and it is probably not a problem in your case. However, it might register a collision when added, before moved.
    • You are scaling the RayCast. This should not be a problem. However, there have been bugs related applying a scaling directly on collision shapes… So, I will avoid this, just to be safe.

    A suggestion: Add a Position node, child of your Shotgun, marking the origin for the RayCasts. Then you can copy the global transform of the Position to the global transform of the RayCasts - and then apply the random rotation - before adding them as children. This should make it easier to update the position if you need to (e.g. if you changed the shotgun model, you can mode the Position node accordingly). It should avoid any typos when writing the coordinates in the code. And it should avoid the pitfalls mentioned above.


    I'll remind you you are supposed to check is_colliding. I guess you are not doing it for demonstration purposes.

    I'll also remind you that the RayCasts update with the physics frame. So, when calling the RayCast from somewhere other than _physics_process you are getting what they registered last physics frame (i.e. just before _physics_process ran last). You can make Godot update the RayCast by calling force_raycast_update on them.


    If you don't need the RayCasts often, having them update every physics frame might be overkill. In that case, you might be interested in checking like this: get_world().direct_space_state.intersect_ray(start, end). See PhysicsDirectSpaceState. However, using RayCast should work. Using intersect_ray is only an optimization.


    Unrelated: if you want to guarantee an uniform probability distribution distribution from the random functions, call randomize once at the start, instead of once per iteration. This is probably not noticeable anyway.