I have a list of objects with multiple stats set up in a dictionary with labels matching the keywords. For each of the 6 stats linked to a keyword I have a slider. The way this app works is the label is visible if the sliders match the corresponding value or if the value is zero.
Right now if there’s a change on a slider then for each of the 37 keys I’m iterating through the sliders and checking each slider against the corresponding value in the dictionary and making the label invisible if at least one value doesn’t match or isn’t zero.
Is there a better way to set this up without iterating through the sliders and dictionary each time there’s a change?
extends Node
var data: Dictionary
func _ready() -> void:
for slider in get_children():
slider.value_changed.connect(_on_value_changed.bind(slider.name)) # Assuming the name of the node is the key in the dictionary
func _on_value_changed(value: float, name: String) -> void:
data[name] = value
# more stuff
Yeah I’ve already done that. What I’m asking is is there a better way than nesting to loops to iterate each slider against each dictionary key when a value is changed. I still need to check all values as there can be multiple true and false for each key
extends Control
@onready var sliders = [$DiffS, $OffenseS, $ControlS, $FearS, $DefenseS, $UtilityS]
func _ready() -> void:
for i in range(sliders.size()):
sliders[i].value_changed.connect(_on_slider_value_changed.bind(i))
func _on_slider_value_changed(value: float, slider_index: int) -> void:
for keys in Global.spirits:
if Global.spirits[keys][slider_index] != value and value != 0:
$SpiritC.get_node(keys).visible = false
else:
var x = 0
for i in range(sliders.size()):
if Global.spirits[keys][i] == sliders[i].value or sliders[i].value == 0:
x = x + 1
if x == 6:
$SpiritC.get_node(keys).visible = true
i guess you could keep track of which labels should be synced to which stats and which sliders, but ut would quickly turn out a bit convoluted and become more difficult to add new sliders, stats and labels to. Unless you experience some issues with your current solution i dont think you need to do anything. I dont think iterating over a dictionary a few times like this will have any meaningful impact on performance unless you do it every frame and probably not even then.
You could also make it so that the sliders only send out signals if the new set value is a value you would care about but again you would end up needing to convolute your code quite a bit and track which values from which sliders are important for which labels. If you care about performance i think it would be better to put that time on something that takes up more CPU, unless you know that this is something that is causing issues.
That said, there are probably simple solutions for this but I can’t come up with any.
how often sliders change? if they don’t change each frame and you don’t have more than 500 iterations it shouldn’t be terrible, as long as it don’t lags - you shouldn’t check for more optimal solution
You’re doing too much checking in that loop. Since a spirit is supposed to be visible only if all stats match the sliders (or are 0), you can early-exit the loop as soon as one of them doesn’t match.
Firstly, in terms of performance we should answer if this is really an issue.I say this, because with 37 keys and 6 stats, you are doing at most 222 comparisons when a slider changes.Consequentially, because sliders are not changing every frame, tha’ts a very small amount of work.
If you would like to optimize it further, you would need to save/store additional state instead of recomputing everything. Below is a paradigm on how you could implement this:
Each key could keep a count of how many slider conditions currently match. When a slider changes, only recalculate that one stat for every key and increment/decrement the count accordingly.Then visibility becomes:
key.visible = (match_count == 6)
The effect of this procedure, is the reduction of work from checking all 6 stats for every key, to checking only the changed stat for every key.