How to make an object call another object's functions

Godot Version

4.4

Question

I’m making a game where in my level there is a player scene and a crafting table scene. I have it to where the player can press a key and create a line trace, which then detects whether the line hits a crafting table, at which point opens a menu. I’m able to get the collider name and such from this interaction.

What I’d like to do is have the player’s crafting resource, such as metal, transfer from the player to that specific crafting table upon clicking a button in the menu. I will likely have multiple players and crafting tables in one level, so it is necessary that these values are stored within the specific instances of those scenes.

The issue that I am having is that, even though the player able to get the name of the object from the line trace, the player scene is unable to interact with the crafting table scene. (By “interact with”, I mean that the player is unable to call the functions of the crafting table and vice versa.) Ideally, I have the player call a function of the crafting table that allows the crafting table to store the amount of metal that player has, then the player would set it’s metal count to 0.

I would very much appreciate some help with this problem. Please feel free to ask me questions, and I will try to respond within a day or so. Thank you all in advance!

To call a function in the script of node A from another node B, node B needs to obtain a reference to node A. Have you already got such a reference? If so, calling a function is as simple as this, as an example:

class_name CraftingTable
extends Interactable # or something

func foo() -> void:
    print("foo")
class_name Player
extends CharacterBody3D

#var crafting_table: CraftingTable

func _interact_with_crafting_table() -> void:
    crafting_table.foo() # "object.function_name(parameters)"

If you have not got a reference, there are multiple ways to get one:

Store a reference to the crafting table scene in the player object.

Yes, but the issue is that these are two scenes in a level, not two nodes in a scene. I’ve indeed tried doing something to the tune of what you have, and thus far, no dice.

How do you suggest I do that? I’ve tried the $.. but that doesn’t even get me the level.

Scenes do not exist at runtime. It’s all just a big tree of nodes. You can get any node from anywhere in the tree if you have a correct path.

Post your scene structure.



Player scene’s top node should have a script that declares a reference to crafting table node. You can then assign that reference in the editor in the test level scene:

@export var crafting_table: Node

Now you can selected the player in the main scene and assign that reference in the inspector.
Even better if crafting table class is named then you can declare the exact type:

@export var crafting_table: CraftingTable

With your current setup where player’s top node has no script you can still do it if that reference is declared in character body’s script by selecting the player in the test level scene, right click on it in the scene tree and enable “Editable Children”. Now you’ll be able to select the character body and assign that reference.

Dunno how but this worked! Thanks!