Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vector elements sometimes return incorrect comparison results. #43476

Open
madmiraal opened this issue Nov 12, 2020 · 7 comments
Open

Vector elements sometimes return incorrect comparison results. #43476

madmiraal opened this issue Nov 12, 2020 · 7 comments

Comments

@madmiraal
Copy link
Contributor

Godot version:
master a7d610d
3.2.3.beta1

OS/device including version:
Ubuntu 20.10

Issue description:
Sometimes, when comparing the element of a vector to the value that it has been assigned, the comparison fails.

Steps to reproduce:
Set an element of a Vector to 0.1 compare the element to 0.1:

var v = Vector2() # or Vector3()
v.x = 0.1
if (v.x == 0.1):
	print("Correct")
else:
	print("Incorrect")
if (v.x > 0.1):
	print("Incorrect")
else:
	print("Correct")

Output:

Incorrect
Incorrect

This does not happen when comparing two variables or two Vector elements, which suggests that the problem lies with the underlying primitive data types being different.

Minimal reproduction project:
FloatComparisonError.zip

@akien-mga
Copy link
Member

I think that's expected, Vector2() holds real_t (which is float by default), while the float type in Variant is double.
You likely get precision issues when going casting from double to float and back.

@Rubonnek
Copy link
Member

Rubonnek commented Nov 12, 2020

Ohh, I think that might also be why I was seeing some ghost noise in the Master audio bus after setting it's volume to '0.0'.

I think this casting precision issue should be documented, or at least hinted at in the is_equal_approx function.

@vnen
Copy link
Member

vnen commented Nov 12, 2020

I believe we should a warning in GDScript for these cases, since floating point comparison can always be problematic. The is_equal_approx() function can be used instead.

@madmiraal
Copy link
Contributor Author

Floating point comparisons are only expected to be problematic after performing (different) calculations not assignments. This problem is due to inconsistent use of data types and implicit casts between doubles and floats that are currently beyond the control of the user.

I think we should stick with one floating point representation, to make sure things are consistent. real_t is already used in a lot of the codebase, and I believe it should be used instead of float or double everywhere. Its typedef is already controlled through a single #define to help avoid the precision/size vs memory debate:

godot/core/math/math_defs.h

Lines 109 to 113 in f733746

#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#else
typedef float real_t;
#endif

@aaronfranke
Copy link
Member

This is the exact same issue as #30426. This happens because Vector2(0.1, 0.1).x != 0.1. GDScript floats are double-precision, while vectors use single-precision. The 32-bit float 0.100000001490116119384765625 is not equal to the 64-bit float 0.100000000000000005551115123126..., so you need to use is_equal_approx() to make comparisons.

A similar issue can be found at #17971, and like that issue, this is a duplicate of godotengine/godot-proposals#892... unless @vnen wants to add a warning to GDScript for this, in which case we can leave this open to track that.

@madmiraal
Copy link
Contributor Author

Although this also applies to equality, the issue is more about greater than reporting incorrectly.

The specific use case I have is detecting whether an object has moved right from its current position. If I try store the x position in a variable, and then check whether the current x position has increased, I get the wrong result if it hasn't changed.

I understand the root cause of the problem, and I accept there are workarounds, but it doesn't change the fact that we shouldn't be using different data types within the engine for storing the user's floating point variables. It causes unnecessary surprises that are difficult to troubleshoot through no fault on the user's part.

@aaronfranke
Copy link
Member

aaronfranke commented Jan 25, 2021

@madmiraal I did some extra work recently for getting double support working, and now it compiles and runs:

Screenshot from 2021-01-25 00-23-51

Here is a link to a Linux debug build with doubles enabled. It's held together by duct tape and prayers, for example it can't open 3D models or SCN files because there is a size mismatch, but in its current state it does run your test code successfully.

CristianoSimao added a commit to CristianoSimao/godot-docs that referenced this issue Jun 1, 2022
Many errors in collisions or vector positions ocur because the Vector3 not store the right values, see this bugs report: godotengine/godot#43476

If some explanation is given in the documentation will help people avoid many time lost trying find the bug, and discovering that Godot like imprecise numbers to calculate position.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants