It can mean a few different things, but it's always just a convention in those circumstances. There is no "enforcement" by the language or rules. Rather, it is simply a way of conveying information to the one reading the source code so that they have a better idea of the meaning behind the method. Uses include:
The method is "private", i.e. it is meant to only be used internally by the class. Other classes outside the scope of the class shouldn't attempt to access it. Many other statically-typed languages actually force this with a
private keyword (C++, C#, Java, etc.), but in GDScript, everything is public on a technical level (you can manually call
_shoot even from outside the object, even if it has a leading underscore).
The method is "virtual" meaning that it is intended to be overridden by a derived class. This may be the case if a script has a custom function with a
pass in it.
pass # let someone derive this class and define what "shooting" means.
This is useful if, say, you want to define a base class that does some boilerplate features, but you want people to extend that base class and inject their own behavior into the middle of those predefined operations, e.g. if I shared my own Ranger class with you that has movement, vision, collision logic, a sprite, etc., but I wanted you to be able to say what happens when they attempt to "shoot" arrows.
In Godot, there is a third case: The method is a "notification", i.e. it is a convenience function that provides users with easy access to certain subsections of the core iteration loop in godot:
_notification(what). The "what" here is an enum that can hold various integer values defined in the global scope with the
NOTIFICATION_* prefix. For example,
_ready() is a shortcut for...
# _ready() content goes here
There are similarly
NOTIFICATION_PHYSICS_PROCESS, and even values that don't have shortcut methods like
NOTIFICATION_TRANSFORM_CHANGED which is triggered on CanvasItem nodes (Node2D/Control) when they are moved, rotated, or scaled. Each of the shortcut methods for a notification have a leading underscore in front of them.
To see what notification enums exist, you should look for "NOTIFICATION_" in the docs and see what pops up. Different classes may use different values and they're displayed as constants for that specific class.