How can I lerp CFrame orientation and position in tandem?

I’m using CFrame lerping to move my pets, however, I’m having issues with making the pet face my player while also lerping the positions appropriately. I’m using the LookVector direction of the lookAt CFrame created from the pet facing the player’s direction, but for some reason, the orientation of my part is not being lerped or is too weak (I think?). Is there any recommendations for how I can go about this?

local petObj = PetFolder:WaitForChild("Dog")
game:GetService("RunService").RenderStepped:Connect(function(dt)
	local rootPart = Character.HumanoidRootPart
	local petOrientation = CFrame.lookAt(petObj.Position, rootPart.Position)
	local targetCFrame = CFrame.new(rootPart.Position, petOrientation.LookVector)
	petObj.CFrame = petObj.CFrame:Lerp(targetCFrame, dt * lerpSpeed)
end)

Your problem is the dt * lerpSpeed.

The second argument of Lerp should be between 0 and 1 – 0 meaning “the current position” and 1 meaning “the target position”.

Try rewriting it so that that number linearly changes from 0 to 1 over a specified time period.

Lerpspeed is a constant between 0 and 1, but however much I change it, the orientation still does not change as much as I need it unfortunately :frowning:

Right, but think about what your code is saying.

Say LerpSpeed * dt ends up being 0.5 each frame. That’s a constant, more or less.

Since you’re basing your lerp on the current position of the part, you’re per-frame progression from the starting point A to the goal position B looks like this:

A - - - - - - - - B
X
        X (move 50% from a to b
            X (move 50% from previous position to B)
              X (etc.)
               X

See the problem?

Sorry about any formatting problems, I’m on mobile.

As for the solution:

Lerp isn’t great for constantly changing things like this. You either need to change your lerp code to not change the start/end positions very often, or you could come up with a new way to move the pets without Lerp.

That’s an odd statement @nicemike40 contrary to this belief Lerp is fine for constantly moving objects if you are looking to make the movement sharp and responsive yet elastic like so if you adjust the lerp alpha enough. That’s what I did for my inverse kinematics project:

However, I believe the problem is actually the CFrame math, especially for the target CFrame.

It’s a common problem you are putting a direction vector instead of a position vector for the second argument of the CFrame.new constructor. If you put a direction vector as the second argument the Pet will tend to look at the origin (0,0,0) hence the pet will tend to not look at the owner at all in fact. However, the pet orientation CFrame obtained by @2Plants is correct the second argument is the humanoid root part position. Consequently, we just need to move the pet to the correct set position away relative to the humanoid.

local petObj = PetFolder:WaitForChild("Dog")
game:GetService("RunService").RenderStepped:Connect(function(dt)
	local rootPart = Character.HumanoidRootPart
local petPositionCFRelativeToHumanoid = rootPart.CFrame *CFrame.new(5,5,-5)

	local petCF = CFrame.lookAt(petPositionCFRelativeToHumanoid.Position, rootPart.Position)

	petObj.CFrame = petObj.CFrame:Lerp(petCF, dt * lerpSpeed)
end)

The numbers 5,5,-5 are arbitrary and you can change to whatever you want depending on how you want to place the pet relative to the humanoid.

3 Likes

My bad for missing that problem, thanks for the correction! I thought the problem was that OP was looking for a linear-speed movement and was getting an ease-out movement, which you’d get with Lerp in this way.

1 Like