There are multiple ways you can programmatically get a reference to a instanced node from another instanced node, each with their own pros and cons.
The simplest way is to use get_parent
and then get_node
. Using the screenshot you posted, you could access the player's variables with this method like this:
# Baddie.gd
extends KinematicBody2D
export (int) var speed = 200
var player = null
func _ready():
player = get_parent().get_node("Player")
var b = player.velocity
What this code is doing is it first gets the parent node, in this case the node named Node2D
, and then uses get_node
to get a child node of Node2D
, in this case we want the node named Player
.
This has the advantage of being easy to quickly write up and use, but this method assumes that the player and the baddie will both be children nodes of Node2D
directly. In other words, you cannot have the Player
node or the Baddie
node parented to any other node than Node2D
, as otherwise it will be able to access each other using the code above.
So long as your node structure doesn't change, this method will work fine.
Another method you can take is exporting the node path to the player node, so you can set which node the baddie gets through the editor. For example:
# Baddie.gd
extends KinematicBody2D
export (int) var speed = 200
export (NodePath) var path_to_player = null;
var player = null
func _ready():
player = get_node(path_to_player);
var b = player.velocity
Then you just need to select the Baddie
node in the editor, and in the script variables you will find that you can assign path_to_player
to a node in the scene.
This method works well if you do not know where the player will necessarily be in the scene. However, this method doesn't really work if you are spawning/instancing enemies dynamically or at run-time, as you cannot easily set path_to_player
in code.
This method is really ideal for levels where all of the enemies and the player are predefined and placed within the level.
Finally, the last method is to define a manger of sorts to access other nodes.
There are several ways to write the manager, but a simple manager could look something like this:
# Attach to Node2D!
extends Node2D
var spawned_entities = {}
func add_entity(entity):
if (spawned_entities.has(entity.name) == false):
spawned_entities[entity.name] = entity
else:
print ("Entity already added to spawned entities")
func remove_entity(entity):
if (spawned_entities.has(entity.name) == true):
spawned_entities.erase(entity.name)
else:
print ("Entity not within spawned entities")
func get_entity(entity_name):
if (spawned_entities.has(entity_name) == true):
return spawned_entities[entity_name]
else:
return null
And then in Player.gd, you would need to add the following:
# Add the following to Player.gd somewhere!
var entity_manager = null
func _ready():
# Insert other code here
# NOTE: getting entity_manager like this may or may not
# not work depending on your project and how the node tree is setup.
# The important part is just getting a reference to it, how you do it is
# up to you. We will use get_parent for this example
entity_manager = get_parent()
# Add the player to the spawned entities
entity_manager.add_entity(self)
Finally, you could get the player in the baddie script using the following code:
# Baddie.gd
extends KinematicBody2D
export (int) var speed = 200
var entity_manager = null
var player = null
func _ready():
# As previously mentioned, you might need to get entity_manager
# differently depending on your project
entity_manager = get_parent()
# Add the enemy to the spawned entities
entity_manager.add_entity(self)
# Get the player from the entity manager
player = entity_manager.get_entity("Player")
var b = player.velocity
The advantage of using a system like this is that so long as your scripts can find a reference to Entity_Manager
/Node2D
, you can access any of the spawned entities added to the spawned_entities
dictionary. Then when a entity is removed, you just need to call entity_manager.remove_entity(self)
before calling queue_free
to remove it from the dictionary.
This makes it easier to access entities that are spawned while the game is running, as so long as you know its name (in the case of the example above), you can get a reference to it. You could also store the entities differently depending on your needs. For example, you could store all of the entities in a list instead of a dictionary.
The downside of this method is it takes a bit more boiler plate code to get going, but if you are spawning/instancing enemies or other entities you need to access from other scripts during run-time, this might be a good way to be able to access them through a single interface.
The other downside with this method is that all nodes still need to get a reference to Entity_Manager
/Node2D
before they can access the other nodes.
Also, I should note that this method really should be tailored to the needs of your game. For example, if there is only ever one player, than storing the player in a dictionary might not be ideal, and instead you might want to define a variable in Entity_Manager
to store the player instead for easier access.
Of course, there are many other ways you could go about it based on what works best for you and your project.
Hopefully this helps! :smile:
Side note: Welcome to the forums!