Comparison reading true when it should be false

Godot Version

4.4.1.stable

Question

I’m working on a settings menu, though right now I just have the sensitivity in it. What should be happening is when the textbox is updated, the slider and the sensitivity variable is updated and same for the slider (save for updating the textbox instead). But for some reason, a specific check always reads true. I tried replacing the check with a different one for similarly buggy behavior.

Here’s the function that manages things:

func _process(delta: float) -> void:
	ReadValue += $HSlider.value
	if $TextEdit2.text.to_float() != Sensitivity:
		Sensitivity = $TextEdit2.text.to_float()
		$HSlider.value = floor($TextEdit2.text.to_float()*100)/100
	elif ReadValue != floor(($TextEdit2.text.to_float())*100)/100 and not (Sensitivity > 0.1 or Sensitivity < -0.1):
		print("Pulled value: ", $HSlider.value, "; Read Value: ", ReadValue, "; Sensitivity: ", Sensitivity, "; $TextEdit2.text.to_float(): ", $TextEdit2.text.to_float(), "; Floor: ", floor($TextEdit2.text.to_float()*100)/100,"; Is different: ", ReadValue != floor($TextEdit2.text.to_float()*100)/100)
		Sensitivity = $HSlider.value
		$TextEdit2.text = str(Sensitivity)
	if $Button.button_pressed:
		FileAccess.open("res://Settings.txt", FileAccess.WRITE).store_string("This is your settings file! I heavily advise against touching it.\n:CamSensitivity:" + str(Sensitivity) + ":")
	ReadValue = 0.0

More specifically the check ReadValue != floor(($TextEdit2.text.to_float())*100)/100 always reads true. This renders the textbox useless, making it difficult to set any sensitivity not approved by the slider.

I had put in the print code to check that it should be false, and sure enough, every single thing I checked had the same exact value, but the check still read true

print("Pulled value: ", $HSlider.value, "; Read Value: ", ReadValue, "; Sensitivity: ", Sensitivity, "; $TextEdit2.text.to_float(): ", $TextEdit2.text.to_float(), "; Floor: ", floor($TextEdit2.text.to_float()*100)/100,"; Is different: ", ReadValue != floor($TextEdit2.text.to_float()*100)/100)

This isn’t the first unsolvable error I’ve had so far. I had another error with my door system that I had to code in checks and work arounds for a point float point precision error. Is this the same thing? Is it something different? Did I miss something specific?

You would have to floor both values to get an integer, you know equals comparisons for floats are a bad idea and should be avoided.

In general though, this script should be broken up into signals from the sliders such as value_changed, and the button’s pressed signal. Running every frame through _process is bad for performance and possibly the responsiveness of the application.

3 Likes

What is the TextEdit equivalent of _value_changed?

I recommend you use a SpinBox. It’s meant for exactly what you’re trying to do and will eliminate all the need for casting and avoid the issues you’re having. It also has a value_changed() signal.

2 Likes

I’m curious why you’re adding $HSlider.value toReadValue and then zeroing ReadValue every frame? It seem like you could achieve more or less the same effect by just assigning the slider value to ReadValue

It seem like what you’re trying to do is get a value with two decimals of precision? Unfortunately, that’s not how floating point works. If that’s what you want, you’re far better using a fixed point scheme with integers; treat the integer values as (in this case…) hundredths.

As @gertkeno says, you can’t do equality checks with float, at least, not if you value your sanity. Floating point is a neat hack, but it has sharp corners, and one of them is that it cannot perfectly represent a wide set of common values. Famously, for instance, without rounding, 1/3*3 is not 1 in floating point.

Rather than using equality testing, you need to either be checking “less than”, “greater than”, or use the is_zero_approx() or is_equal_approx() functions; those test to see if the float value is within some epsilon of the desired value. Even those can get hairy with large numbers; it’s trivially possible to have a floating point number that is large enough that adding 1.0 to it doesn’t actually change it.

A lot of the nonsense in the code is because most of the function had this or that seemingly unsolvable issue. It’s a != because < or > broke completely due to their own issues. The += instead of = is because I needed to preserve it’s status as a float. I did the same thing with a different value since the floor function always spits out an integer…that can also be a decimal. It’s the way it is because of the strange errors.

floorf() will take and output float values.

It’s also worth noting here that 100 is an integer, not a float value. If you want a float value, use 100.0.

The spinbox does indeed work better, and actually has a _value_changed function, unlike the textbox.

I probably should have quoted you both in one message, but I forgot. oops!

What gertkeno suggested seems to be working a lot better than my other mess, but I am having a bit of trouble with my spinbox, as it doesn’t seem to trigger _value_changed when the value changes. Is there anything specific I need to do to get it to recognize?

the virtual override only works if your script is attached to that node, it seems like your original script would be a parent of this sensitivity control. Try using the signal value_changed instead.

1 Like

I swapped from using one parent script to using individual scripts. The script that checks if the spinbox value changed using _value_changed is attached to the spinbox. I’ll try the suggestion anyway, though.

I believe there’s a boolean value you may need to check or uncheck on the SpinBox called update_on_text_changed. If you want it to update whenever the value is changed, use update_on_text_changed = true. Otherwise it only triggers when submitted.

1 Like

@gertkeno Using value_changed and a check under _process (as a quick test) showed that the func _value_changed wasn’t responding at all.

@dragonforge-dev I tried putting $".".update_on_text_changed = true under _ready, but nothing changed.

I think I may just take the easy way out and leave out the slider changing on the spinbox changing. I don’t want another headache on this, and at least I can still request the spinbox’s value, even if I can’t run anything on it changing.

Thank you for the help, both of you! I’m going to mark gertkeno’s original comment as the solution and call it a day.

1 Like

If you want to check out how I handled similar situations, you can take a look at my game template project. I have a bunch of settings managed in there.

It can be set in the editor; just under Editable.

Which I had done. When you experience enough issues over one thing, you tend to just try stuff and see if it sticks.

Also this topic is solved, what are you doing here?

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