Help with groups

Godot Version

4

Question

I’m trying to get access to a variable (not static) that is apart of an object (rock) script, I’ve done this before using groups, so I made a new “rock” group and added the main node to that group. Now what I’m trying to do is to use that variable on another script which is on another node in another scene.

I obviously thought that @onready var rockscript = get_tree().get_first_node_in_group("rock") would work, but apparently not? Because when I try call that variable it says invalid access to property etc on type null instance??

Any help would be super helpful right now xD

That means you don’t have any node inside the scene tree that is from “rock” group. How you added this node on the “rock” group? Have you added the node inside the scene tree?

hey mate, yea I did add it, and I tried switching the “rock” group from global to scene and from scene to global, did nothing

heres the rock scene
image

and heres the groups:
image

also if you’re wondering if I’ve added the “rock” node to the main scene tree where I am trying to call the variable on a different script, no, and I can’t because my game won’t work if I do.

But if you don’t add the node in the scene tree, you can’t expect to get him from groups, because the engine only knows the node is inside some group when the node is added to the scene tree. What is your objective with your code and what happens when you add the node in the scene?

Okay so I really just want to create instances of rocks into my main scene and be able to access a variable that is on the rock script within a node in my main scene that acts as the spawner. How would you propose I do this? I tried to access the variable via the instance but that just gave me a NIL error? And when I tried to use the get_tree.get_first_node_in etc ON the actual rock script and then tried to call that within my spawner script it also gave me an error saying that the property doesnt exist

Can you show the code from your main scene?

yea sure thing, just ignore that I suck at naming things
Heres the spawner script:

extends Node2D
class_name spawner

@onready var ROCK = preload("res://scenes/rock.tscn")

var spawn_index: int
var spawn_count = _rand_spawn_count()

var spawn_list = [
	Vector2(0, 0),
	Vector2(32, 0),
	Vector2(64, 0),
	Vector2(96, 0),
	Vector2(0, 32),
	Vector2(32, 32),
	Vector2(64, 32),
	Vector2(96, 32),
	Vector2(0, 64),
	Vector2(32, 64),
	Vector2(64, 64),
	Vector2(96, 64),
	Vector2(0, 96),
	Vector2(32, 96),
	Vector2(64, 96),
	Vector2(96, 96)
]

func _process(delta: float) -> void:
	_spawn_check()
	print()

func _spawn_check() -> void:
	if (get_child_count() < 4 or ROCK.rockscript.count == spawn_count) && spawn_count > 0:
		_spawn()

func _spawn() -> void:
	var spawn_rate = randi() % 20 + 1
	if spawn_rate == 1:
		if spawn_index != 0:
			var instance: Button = ROCK.instantiate()
			get_tree().get_first_node_in_group("main").add_child(instance)
			var pos = randi() % spawn_index
			instance.position = spawn_list[pos]
			spawn_list.remove_at(pos)
			spawn_index -= 1
			spawn_count -= 1

func _rand_spawn_count() -> int:
	var spawn_count = randi() % 10 + 1
	return spawn_count

And heres the rock script:

extends Button
class_name rock

@onready var rockscript = get_tree().get_first_node_in_group("rock")

var tween_hover: Tween
var durability: int = 4
var count: int = 0

func _on_mouse_entered() -> void:
	if tween_hover and tween_hover.is_running():
		tween_hover.kill()
	tween_hover = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC)
	tween_hover.tween_property(self, "scale", Vector2(1.05, 1.05), 0.5)


func _on_mouse_exited() -> void:
	if tween_hover and tween_hover.is_running():
		tween_hover.kill()
	tween_hover = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC)
	tween_hover.tween_property(self, "scale", Vector2.ONE, 0.5)

func _on_button_down() -> void:
	durability -= 1
	if durability == 0:
		self.visible = false
	if tween_hover and tween_hover.is_running():
		tween_hover.kill()
	tween_hover = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC)
	tween_hover.tween_property(self, "scale", Vector2.ONE, 0.5)
	count += 1


func _on_button_up() -> void:
	if tween_hover and tween_hover.is_running():
		tween_hover.kill()
	tween_hover = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_ELASTIC)
	tween_hover.tween_property(self, "scale", Vector2(1.05, 1.05), 0.5)**strong text**

right now print() does nothing because I cant get the stupid rock system to work xD

I’m trying to access the variable count from my rock script in my spawner script but I have no idea how to do that

The first problem i see here is the ROCK.rockscript.count, ROCK in your code is a PackedScene (a preload of your scene) so you cant access anything from there, this code is to limit the max amounts of rocks spawned at time? Because in this case you can limit that with:

func _spawn_check() -> void:
	if get_tree().get_nodes_in_group("rock") < 4 && spawn_count > 0:
		_spawn()

Also you can explain why you need the count value to spawn the rocks? Because at the start of the scene you’ll have no rock in scene, and with no rock in scene you can’t access the variable count because you don’t have any rock. Also, when you start to spawn the rocks, any rock count will be valid? Because with two or more rocks you needs to choice which rock you want to check the count value

Yea sorry, I really suck with naming stuff, basically the rock “count” is not really to count how many rocks in order to limit them, I already got that far, the problem is that I want to respawn a random number of rocks everytime the player has destroyed all the rocks on screen, so count is not to count how many rocks there are but actually to count how many rocks have been destroyed, so that when the number of rocks destroyed matches the number of rocks that were spawned we can then spawn some more

Okay, before i write the code to help you i just need to understand one more thing, the count in this case is the “durability” of the rock, like you need to hit the rock 4 times to break them, right?

yes indeed, but I’m pretty sure we could add this pretty easy by just multiplying the spawn_count by 4: so if count (durability of rocks) == spawn_count * 4: etc

Okay, i’ll write the code with some explanations, gimme some minutes

no problem, and really thank you so much, this is such a big help, I only started godot about a month ago

I got to go, it’s late where I am, thanks again I’ll reply when I can