I'm trying to make a timer to update an object, but when I press the button that starts the start() function, which in turn starts the start() function, errors occur

Godot Version

4.2

Question

Hi all, I’m trying to make a timer to update an object, but when I press the button that starts function, which in turn starts the start() function, errors occur. I am new to Godot and may have done something wrong. I have attached the code below:

extends Node3D

class_name Building_barrack

var level = 1
var upgrade_cost = 100
var upgrade_time = 5.0
var сapacity = 20

func start_upgrade():
if can_upgrade():
GameGlobal.money_d -= upgrade_cost
$UpdateTimer.start()

func upgrade():
level += 1
upgrade_cost += 100

func can_upgrade():
if level == 1:
if GameGlobal.money_d > upgrade_cost:
return true

func _ready():
pass

func _process(delta):
pass

func _unhandled_input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT:
if event.pressed:
print("Left button was clicked at ", event.position)

func _on_update_timer_timeout():
upgrade()

1 Like

What’s the error that you’re getting?

Attemt to call function ‘start’ in base ‘null instance’ on a null instance

If this is the line that causes the error

 $UpdateTimer.start()

then what that means is that it can’t find the node at the path “UpdateTimer”. This means that the node this script is attached to does not have a node called “UpdateTimer” as a direct child. Either the node is somewhere else or you spelled the name wrong.

Yes, this line, but timer name is true

I think you should start with creating an onready var for the Timer.

You can type it out like:
@onready var timer: Timer = $UpdateTimer

But better yet, drag UpdateTimer from your scene window, and hold left CTRLwhen dropping it in your code box. It will create an onready var for you with the correct path.

replace $UpdateTimer in can_upgrade() with the onreadyvar you just created, in my case: timer.start()

Since it is now an onready var, it will (if I am not mistaken) get initialised even before _ready

Thanks for help!
I try it, but i get new error

Your UpdateTimer. it has a signal, what codeblock does it invoke? What should the timer do once started?

If I understand the question correctly, it should count down the time and run the update function when it is finished.

Your UpdateTimer node has a signal attached to it. Where is it connected?

i can’t see update function in your screenshot. so I am interested in what happens when the timer reaches 0. What signal is given and what codeblock does it want to execute?

This signal
Godoterr

Not sure if it will help, but I made the mistake of trying to use things in a scene before I’d added them to the tree. So if this scene (“Barrack_1LL”) is being instantiated from another GDScript, you may need to make sure its in the tree before you try to access the “update_timer” var.

Also, something I’ve come to love in godot is the debugger. When you have an error, you can use debugger tab to see the variant stats at that exact point in time, which is incredibly handy.

Hope it helps!

Looking at what the debugger writes in the variable filter I realized that the variable with timer is equal to Null, but I don’t know why.

Perhaps I need to create the timer directly through the code as a new instance

Might be worth throwing something like

print("Barrack_1LL Ready")

into the _ready func in your building_barrack file, and also put a

print("start_upgrade") 

into the can_upgrade(): if section before the timer start,

Then when running the problematic section, see which one happens first.
If your “start_upgrade” appears in the “output” first, than it is called before the building_barrack class has been added to the tree, and would explain why update_timer is null (because it is set up onready, which occurs once the item is in the active tree)

So you would need to add it to the active / current tree with something like add_child(class instiantiated object), or having it in a scene that is loaded into the current / active tree.
Not sure if I’m using the right terms here :slight_smile:

Thanks, i’ll check it

I think the problem is in the start_upgrade() function, because the timer problems happen when $Timer.start() function is in it, maybe the problem is that the tart_upgrade() function is called in another script, but I don’t know how to solve it :slight_smile:

I’ve changed the code and hierarchy a bit to something I think is more convenient. After checking a few variants, I realized that the timer.start() function gives an error when it is in the start_upgrade function, which is called in the function handling the button press signal in another scene.
I think I’m getting closer to a solution.


So, I finally came up with a solution, myself, I’m really glad I did!!!
Solution:
I simply made the timer a child of the UI interface, rather than the object in which I have the Building_barrack class created. And already here I made the necessary interactions with the timer.

Thank you all very much for your help, you really helped me to understand, I made sure that Godot community can be relied on, even though I solved my problem myself.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.