I’m trying to find a way to figure out whether or not there is a NaN (not a number) component in a CFrame. I’ve created a few solutions, however, I don’t think they’re the best they can be. The first problem was that when you try to get the type of a variable that is NaN, it will tell you it’s a number:
print(math.asin(2)) --> nan
print(type(math.asin(2))) --> number
Since there’s no unique type I attempted a few other solutions
local function HasNaNComponent(cframe)
return tostring(cframe:GetComponents()):find("nan") ~= nil
end
print(HasNaNComponent(CFrame.new(math.asin(2), 0, 0))) --> true
print(HasNaNComponent(CFrame.new(1, 0, 0))) --> false
This was giving me the correct result, however, turning the components into one big string felt like an unnecessary step, so I tried looping through the components. Apparently, two NaN values are not equal to each other, even when you use the same method to get both values, for example, math.asin(2) ~= math.asin(2).
local function HasNaNComponent(cframe)
for _, component in pairs{cframe:GetComponents()} do
if component ~= component then
return true
end
end
return false
end
This function yielded the same results as the previous one. However, there’s a problem with this one as well, I need to turn the components into a table. Is it at all possible to avoid creating tables or strings to get the result I’m looking for?
Can I ask what situation you need this for? Because it seems like a strange thing to want to do.
Anyways, if you’re really concerned about making a table (which you shouldn’t be) you could just write out the twelve if-statements by hand. Or maybe check value-equality on the Position and Right/Up/LookVectors, that might work because Vector3 equality works differently than CFrame.
I’m lerping a model from one position to the next, and for whatever reason, sometimes the lerp is giving me NaN values. So there might just be a problem with the way I’m lerping. This is the function:
local function LerpModel(model, cframe)
local start = model:GetPivot();
local t = 0;
while t < 1 do
model:PivotTo(start:Lerp(cframe, t));
t += Heartbeat:Wait()*rate;
end;
end;
I’m not so sure about that because of floating point precision. I guess it would work fine if you’re comparing a reference to itself (like the triple = operator)
That sounds impractical. CFrames are riddled with metatables, hooks, and self-calling functions and they are by nature quite heavy (when compared to Vector3s and other datatypes). I don’t think micro-optimizing that function will make any significant difference.
If you still want to try, you’ll need to benchmark the function with different configurations, such as using ipairs over pairs or generalized iteration, tweaking the logic expression, switching out the colon operator, etc.
I have another function that rotates the model in the direction of the target V3, then makes the model start moving in that direction. The first lerp I do to rotate it toward the target isn’t giving me any problems, however, moving it towards the target is.
local angle = CFrame.lookAt(root.Position, position);
local _, _, _, m00, m01, m02, _, _, m12, _, _, m22 = angle:GetComponents();
local oriented = CFrame.new(position)*CFrame.Angles(
math.atan2(-m12, m22),
math.asin(m02),
math.atan2(-m01, m00)
);
The variable named “oriented” is the cframe being inputted to the function. I will admit, that I used a strange method of keeping the direction of the rotation when the model is moving.
I would definitely try clamping the value of the matrices. I’ve encountered a similar problem before where dot product returned a number that’s slightly beyond the [-1, 1] interval, which caused my math to break down.