Yes, Yes, I know I quit and I shouldn’t be posting this, but eh… there’s no way I could possibly make anyone upset if all I do is file a bug report, might as well be a little useful, so I’ll drop this here and be gone again
This produces NaNs in the rotation matrix, would like a fix (default to identity matrix rotation), likely it’s an issue with bad math in how you handle zero vectors
You don’t, but it often happens by accident and because you don’t expect this behavior, it can be game breaking
In my particular case, when a player joins my game, they get a table of units pulled immediately from the server, then, if the unit was moving, there’s a slight chance the new position of the unit arrived in the pull, before the movement packet arrived, causing the unit’s CFrame to be set to looking at it’s current position, turning it’s rotation matrix into all NaNs, making the next movement of the unit push it into a position infinity away, this bug has taken me weeks to dissect because all that seems to happen is the units don’t show up if you join the game, or respawn, I spent tons of time reviewing my code, checking that it wasn’t parenting the unit to nil, seeing why the units were gone, etc, and it was such a rare issue it was almost impossible to repro in a controlled environment, which is tons of dev time, and much grief spent over a simple thing like an improperly written CFrame function
Although, that being said, I have already patched this issue in my game, but I’m pretty sure someone else will run into this problem sooner or later, and have the same headache as me (although hopefully not in nearly as complex of a system as mine, having to sift through 2k lines of intricate code for a rare bug that on the surface appears to be completely different)
This shouldn’t be fixed, it’s a garbage-in-garbage out scenario. If you tell CFrame.new to do something that doesn’t make sense it shouldn’t try to hide the problem and give you back a reasonable output.
The documentation should probably make it more clear that you have to be careful to think of this case that you’re talking about when using the function (maybe the engine should even output a warning in that case?), but I don’t think that it should be “fixed” to try to produce some valid (but probably not what the coder wanted) output.
This bug report was nine years ago but I feel it’d be helpful for anyone else who experiences this in the future. Not sure if it’s something that should be changed in engine, or be clarified through documentation that there are edge cases that could cause this issue to decimate physical parts of your game which rely on lookAt / CFrame.new(x, y).
I have an NPC which looks at nearby players, and the player is spawned in on top of them, shortly before they start wandering around. I have an AlignOrientation in this NPC which sets its CFrame to lookAt the nearest player. It would multiply each vector in CFrame.lookAt by Vector3.new(1, 0, 1), so that the NPC won’t have their body look up or down.
While testing, at some point I noticed that all of the NPC’s limbs and parts would disappear from both the client and the server - I initially thought this had something to do with streaming by toggling it off where it didn’t seem to happen, and the micro profiler would have streaming labels causing lag spikes, as well as large empty gaps where it wouldn’t show anything. Turns out that it’s because both Vector3s initially equal each other, it causes the NPC’s AlignOrientation to try to align the body to NaN, which might’ve caused the world destroy height to remove every part in the model, even if the Workspace property is set to 0/0 which sorta removes the destroy height.
Here’s a simple fix/workaround for AlignOrientation if you’re doing something like what I was doing, where either all or none of the rotation vectors will become NaN. I don’t use the CFrame position for the AlignOrientation, but I decided to include it in case if someone wants it reserved. Note that this won’t check every value in the matrix.
local function NormalizeAngles(CF: CFrame): CFrame
local R00 = select(4, CF:GetComponents())
if R00 == R00 then
return CF
else
local identity = CFrame.identity
return CFrame.fromMatrix(CF.Position, identity.XVector, identity.YVector, identity.ZVector)
end
end
I got a change rolling to have the CFrame.lookAt and CFrame.new return an unrotated CFrame in that case instead. Expect a change to ship for this a few weeks from now.
Though understand that for ideal behavior you probably still need to handle the a = b case explicitly in most cases (e.g.: Remembering and retaining the orientation the thing last had before a became equal to b).