Lerping only the angle of a cframe causes it to wrap all the way around when facing backwards

I am trying to make a custom humanoid system, and currently I am rotating only the Y rotation of the humanoid to face the movement point. It works fine, but I encountered an issue where since the angles are between -180 to 180, if I’m facing slightly left backwards (-170) then turn slightly right (190) the lerp function wraps all the way around and the bot does a 360.

Here’s a gif demonstrating the issue:
https://gyazo.com/1fa41fdd0f2b108a0c06b64d98946b6e

If anyone knows a solution to this please tell me! This is the code I’m using:

local function lerpYOrientation(targetCFrame, currentYAngle)
	local xRot, yRot, zRot = targetCFrame:ToOrientation()
	local alpha = 1 - (1 / 1e+12) ^ math.clamp((lastPhysicsDeltaTime - lastFrameDeltaTime), 0.005, 0.05)
	
	local lerpedRot = currentYAngle + (yRot - currentYAngle) * alpha
	
	return CFrame.new(targetCFrame.Position) * CFrame.Angles(xRot, lerpedRot, zRot)  
end

I think, it because of Gimble Lock.
you can search that trouble on the internet if you want to know more.

but if you want to have solution, you should rotate with CFrame Functions and Lerping it with CFrame

1 Like

Do all the math on the CFrame itself, not its angles.

There’s a Lerp method for CFrames you can use.

1 Like

I’m making a game that plans to have thousands of humanoidless bots using this system, lerping a CFrame is far more expensive than lerping a single number.

I believe gimble lock only applies when you’re dealing with 3 axes. I am only dealing with one axis here.

I think, your lerp method only works for plain numbers not suitable with angle’s, your method prefers the long way on transition between 180 and -180

if you want to have solution, i suggest use CFrame for both Rotating and Lerping

local function lerpYOrientation(targetCFrame, currentCFrame)
	local alpha = 1 - (1 / 1e+12) ^ math.clamp((lastPhysicsDeltaTime - lastFrameDeltaTime), 0.005, 0.05)
	return currentCFrame:Lerp(targetCFrame,alpha) 
end
2 Likes

Like I said in the earlier reply, I am planning to have a lot of this script running at once and lerping all the components of a CFrame is far more expensive than just one number.

Have you checked this? Computers are insanely good at multiplying two matrices together.

Are you even sure that Lerp is slower than the call to ToOrientation?

1 Like

then you should change your lerp algorithm suitable with angles,
you can inspect this code Lerp between two angles (degrees and radians) (github.com)

1 Like

Ok, so I decided to just use the CFrame:Lerp method even though I wanted to avoid it. Upon seeing all the steps that the code @BeatlessOghuz posted, I think CFrame:Lerp will be around the same or better. However, if you are looking for a solution to the original problem that’s not CFrame:Lerp(),the code beatless posted in the github link looks right and probably works if you translate it. If anyone is curious or wants to use my solution, here is the code:

local function lerpYOrientation(targetCFrame, currentCFrame)
	local currentAngle = CFrame.Angles(0, select(2, currentCFrame:ToOrientation()), 0)
	local targetAngle = CFrame.Angles(0, select(2, targetCFrame:ToOrientation()), 0)
	return CFrame.new(targetCFrame.Position) * currentAngle:Lerp(targetAngle, 0.1)
end
1 Like