This code is meant to deactivate the bullet and send it back to the pool once its lifespan runs out. I also have a node with a script that manages several things in my scene tree, and in its _ready() function is this:
for i in 500 :
for type in BulletManager.bullet_pool :
var objShot = load(BulletManager.BULLET_DIRECTORY + type + ".tscn").instantiate()
BulletManager.bullet_pool[type].append(objShot)
get_tree().get_root().add_child(objShot)
But whenever I shoot a bullet, I get the error Cannot call method 'create_timer' on a null value. I figure this means get_tree() is returning null in the bullet script, which should only happen if the bullet nodes are not in the scene tree, but by all accounts they should be. I added the bullets as children of the tree’s root at the beginning, before any bullet is fired.
First step is set a breakpoint on the line await(get_tree().create_timer(lifespan).timeout) (or just before on a pass line).
When the debugger breaks check in the Scene tree panel and click on the Remote tab (left of the Local). Then expand the tree accordingly to see what’s going on with the live system.
Hi! I still don’t know exactly why this happens, but basically, the node needs to be “ready” (inside the SceneTree) before you can create the timer inside the tree. I solved your problem by adding “await(self.ready)” on the start of my code, my script example became like this:
The node that will call the bullets
func _ready():
for i in 5 :
var objShot = load("res://slimepudding - Create Timer Problem/bala.tscn").instantiate()
pool.append(objShot)
call_deferred("add_child", objShot)
pool[0].active()
I tried that, and now at least the bullets are added to the scene tree. Thank you! However, now the bullets just aren’t despawning with the lifespan timer. It’s as if the lifespan variable is being counted as null. This is my bullet spawning function:
for i in 6 :
CreateShotA1("ball_M", 2, global_position, 60, 0, 60, (2*PI*i)/6, 0, 3, 5)
Lifespan should be 3 when this code is run. Printing lifespan even results in 3 when I put it in the bullet’s activate function. Furthermore, whenever I try running deactivate(), I get the error Invalid access to property or key of type 'String' on a base object of type 'Dictionary'. This is what my bullet manager’s dictionaries look like:
hmmm, so, the problem is probably in calling the “activate()” function while the node has not been fully loaded (because get_tree() will always return the tree in which the node is inserted, and will return an error if the node is not inside the tree), so much so that if you call the same function in _process(): it will work normally.
I did this changes in my test project and its still working properly
func _ready():
for i in 5:
var objShot = load("res://....tscn").instantiate()
pool.append(objShot)
get_tree().get_root().call_deferred("add_child", objShot)
await(pool[i].ready)
# or: await pool[i].is_inside_tree()
pool[i].active()
My assumption is that you should put the “await bullet.ready” right after you create the nodes (has i did in my for loop), or add a condition in CreateShotA1. I suppose this should, work:
func CreateShotA1(...):
var objShot = get_available_bullet(bullet_type)
if not objShot == null && objShot.is_inside_tree() == true:
...
(It’s a common problem in godot 4 apparently), if nothing ended up working, use a instantiated Timer instead, atleast until you figure out what is the solving key.
By the way, I’m not running the activate() function when the bullets are instantiated at the beginning; I’m running it when they’re fired through the function CreateShotA1. My intention is to deactivate the bullets and put them in the pool when they’re first instantiated, so they can be activated when fired, and then put them back in the pool after their lifespan timer is don.
all of them worked properly, so i could not understand what is the problem.
Here’s how i did:
extends Node2D
var pool = []
var bullet_pool : Dictionary = {
"ball_M": [1],
"knife": [],
}
func _ready():
for i in 5:
var objShot = load("res://....tscn").instantiate()
pool.append(objShot)
get_tree().get_root().call_deferred("add_child", objShot)
bullet_pool["ball_M"].append(pool[i])
pool[i].active()