Add Vector2:FuzzyEq to match Vector3:FuzzyEq

As a Roblox developer, it is currently too hard to check the fuzzy equality of two Vector2s.

Here are 3 reasons to support why Vector2:FuzzyEq should be added.

1. Consistency.

Vector3 has a FuzzEq method. This alone is enough to warrant a Vector2:FuzzyEq because both are vector types that have valid use cases for fuzzy equality (see #2).

Furthermore, on multiple occasions I have written a function that operates identically on Vector2s and Vector3s yet needs custom logic for performing fuzzy equality. This is inconvenient.

2. Fuzzy equality is practical.

Consider the spring module I am writing for an animation library that fires a Completed event when the spring reaches its target. Without a fuzzy equality, the event might never fire, as the spring could be very slightly and slowly oscillating around its target. Yet, for all visible intents and purposes, it has reached its target.

3. Writing your own fuzzy equality is slower.

A custom implementation of Vector2:FuzzyEq looks something like this:

local function Vector2FuzzyEq(v1, v2, epsilon)
	local v1x, v2x = v1.X, v2.X
	if v1x == v2x or math.abs(v1x - v2x) <= (math.abs(v1x) + 1) * epsilon then
		local v1y, v2y = v1.Y, v2.Y
		if v1y == v2y or math.abs(v1y - v2y) <= (math.abs(v1y) + 1) * epsilon then
			return true
		end
	end

	return false
end

To gauge how this might compare to a Vector2:FuzzyEq, we can benchmark an up-dimensionalized version against Vector3:FuzzyEq.

Benchmark info

Benchmarked with Benchmarker Plugin using 10 seconds.

local function Vector3FuzzyEq(v1, v2, epsilon)
	local v1x, v2x = v1.X, v2.X
	if v1x == v2x or math.abs(v1x - v2x) <= (math.abs(v1x) + 1) * epsilon then
		local v1y, v2y = v1.Y, v2.Y
		if v1y == v2y or math.abs(v1y - v2y) <= (math.abs(v1y) + 1) * epsilon then
			local v1z, v2z = v1.Z, v2.Z
			if v1z == v2z or math.abs(v1z - v2z) <= (math.abs(v1z) + 1) * epsilon then
				return true
			end
		end
	end

	return false
end

return {
	ParameterGenerator = function()
		local v1 = Vector3.new(math.random(), math.random(), math.random())
		local v2 = Vector3.new(math.random(), math.random(), math.random())
		return v1, v2
	end,

	Functions = {
		["Vector3:FuzzyEq"] = function(Profiler, v1, v2)
			for i = 1, 1e5 do
				local eq = v1:FuzzyEq(v2)
			end
		end;

		["Custom FuzzyEq"] = function(Profiler, v1, v2)
			for i = 1, 1e5 do
				local eq = Vector3FuzzyEq(v1, v2, 1e-5)
			end
		end;
	}
}

We see from this that Vector3:FuzzyEq is about 4.12% faster than our custom implementation. This speed increase becomes significant and necessary when the method is being run many times per frame.

Lastly – while on the topic of speed – improvements were recently made with the native Luau Vector3 Beta. And with similar improvements planned for Vector2, now seems like a fitting time to add the method.


If this issue is addressed, it would improve my development experience because Vector2s and Vector3s would behave more consistently, and I would not have to write my own slower version.

EDIT: Fixed benchmark

56 Likes

Supporting because consistency is good.

7 Likes

On more than one occasion I have wished for Vector2:FuzzyEq.

5 Likes