I’m trying to make a game in which I need that the player can change the time into a specific minute and hour. I’ve made the base time system that goes flowing in the game (following a tutorial) and made an UI so the player can select the hour and minute when interacting with it. The problem is that, even searching similar problems for various days, I can’t find the way that the selected time can substitute the current one.
Here’s the time system code:
extends Resource
class_name DateTime
@export_range(0,59) var seconds: int = 0
@export_range(0,59) var minutes: int = 0
@export_range(0,59) var hours: int = 0
@export var days: int = 0
var delta_time: float = 0
func increase_by_sec(delta_seconds: float) -> void:
delta_time += delta_seconds
if delta_time < 1: return
var delta_int_seconds: int = delta_time
delta_time -= delta_int_seconds
seconds += delta_int_seconds
minutes += seconds / 60
hours += minutes / 60
days += hours / 24
seconds = seconds % 60
minutes = minutes % 60
hours = hours % 24
And the time system that updates it:
extends Node
class_name TimeSystem
signal updated
@export var date_time: DateTime
@export var ticks_per_second: int = 60
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
date_time.increase_by_sec(delta * ticks_per_second)
updated.emit(date_time)
and here is where I’m trying to make the time change UI:
I’ve tried tons of little things without use, tried with signals but couldn’t make it work either, like it is now in particular it just crashes with the error (“Invalid set index ‘hours’ (on base: ‘GDScript’) with value of type ‘int’.”)
I don’t have any clue on how to proceed with it. I suppouse the best way must be related to use signals but…
Truth be told, the code is a pain to read if you don’t use the preformatted text option, it’s hard to make sense of code indentation.
Right now I believe you are updating the time by calculating the delta into a variable that holds the time that elapsed.
You also emit a signal once every frame which is kinda hardcore but if it works, it works.
I would like to know what is currently not working and how it’s looking like ingame. Based on code, I assume you have several buttons to increase/decrease hours and minutes and then an extra button to confirm the changes (wait button).
After pressing the wait button, does the values change?
I would put a breakpoint at the line date_time.hours = temp_quantity_hours and then see in the remote tab if date_time.hours adjusts to the value of temp_quantity_hours. If it does adjust, please go line after line and see if anything in the code procedure could “revert” the number back.
it just crashes with the error (“Invalid set index ‘hours’ (on base: ‘GDScript’) with value of type ‘int’.”)
this just means that your @onready var date_time := DateTime returns null and the value doesn’t actually exist
Oh, sorry, I’ve edited it with the preformatted text option, thanks. ^^
I forgot to add the TimeUi part, where the time labels are updated to show the time:
extends Control
class_name TimeUi
@onready var hours_label: Label = $ClockControl/Hours
@onready var minutes_label: Label = $ClockControl/Minutes
@onready var timeUi = $"."
func _ready():
timeUi.visible = false
func _input(event):
if Input.is_action_pressed("showClock"):
if timeUi.visible == false:
timeUi.visible = true
elif timeUi.visible == true:
timeUi.visible = false
func _on_time_system_updated(date_time: DateTime) -> void:
update_label(hours_label, date_time.hours)
update_label(minutes_label, date_time.minutes)
func add_leading_zero(label: Label, value: int) -> void:
if value < 10:
label.text += "0"
func update_label(label: Label, value: int, should_have_zero: bool = true) -> void:
label.text = ""
if should_have_zero:
add_leading_zero(label, value)
label.text += str(value)
What I suppouse is that I have just to access the “minutes” and “hours” variables in the DateTime resource class from the TimeSelect one when the “Wait” button is released to copy there the values entered in the UI of the TimeSelect, but it always crashes giving me a null type of error.
but it always crashes giving me a null type of error.
it crashes because the handle is null, it cannot find date_time.
Did you rename the node in your SceneTree? is it actually in the sceneTree or is date_time an autoload? Autoloads don’t require a handle, you can directly set the values with DateTime.hours and DateTime.minutes.
date_time it’s a Resource, not linked to any node, so it is not in the SceneTree.
I’ve tried to make it an autoload to try if it worked but it fails to load because “Failed to instantiate an autoload, script ‘res://Time/date_time.gd’ does not inherit from ‘Node’.” (By the definition of the Resource class it seems like it works in part similar to an autoload by itself?)
incase of @export var date_time: DateTime within your TimeSystem class, that seems to work and your date_time variable is accessible.
Could you see if you could use that statement for your TimeSelect as well?
“Failed to instantiate an autoload, script ‘res://Time/date_time.gd’ does not inherit from ‘Node’.”
All Autoloads inherit from Node and you can create them in Project → Project Settings → Globals.
The thing about autoloads is that those are global classes that can be accessed everywhere and don’t need any fancy signals. They exist the moment you run the game and persist throughout your game running even when you change your scenes. You also don’t need to create local variables or exports to hold the instance.
I’ve tried to use an autoload SignalBus (that was already created for sending a signal for a dialog system that works) to emit a signal from one of the scripts to the other but still can’t update the time…
I have difficulty understanding your flow of code.
Usually when you connect to a signal, you specify which method within the script you want to execute as a reaction.
In your code, your time_select emits the time_change signal the moment it enters the SceneTree but all it does is getting picked up by date_time who then calls the method back to time_select. It’s super weird.
Where is your actual hours and minutes saved? It’s your class DateTIme, right? I then believe they’re in date_time.gd