Traversing from UserInterface node, path to CanvasModulate is
.. steps up in hierarchy: Player > Ysort > Village from which descent into CanvasModulate.
This, while is plausible way to do it however, is very prone to errors. What if you move things around? What if you put your player scene in some other scenario? For these reasons, it's better to use one of following:
1) Use export variable
This option is good, because the path is settable from the editor. If something moves, editor takes care of updating the path. In your case, you also need to set player's children editable (right click/editable children) since it's separate scene in order to set the path.
export var canvasModPath : NodePath
onready var canvasMod = get_node_or_null(canvasModPath)
Note: check that the variable isn't null before using it, so you won't get errors in surprising situations (unless error is more desirable than silent fail).
2) Use groups
This one's also nice for finding something you don't always beforehand. You need to add the CanvasModulate node in a group, in this case called "Weather". You can manage groups by selecting the node and switching in the right (inspector) panel to Node tab > Groups.
func _ready() -> void:
var weatherGroup = get_tree().get_nodes_in_group("Weather")
if weatherGroup.size() > 0:
# Get first node and ignore if there's more
canvasMod = weatherGroup
3) Use find_node()
This option is sometimes handy, if there's too much going on and you're sure how the needed node is named and no other nodes share that name. You should name the node more uniquely, for example
WeatherCanvasModulate. You then can find it with following code:
This solution, does again presume some things about node structure, which does has it's own hazards. If you return to your game after a few weeks or months break, you might not remember that node name has certain significance and might break it unintentionally.