Hello! I’m new at roblox scripting and I was learning how to make that the character’s face follow the player’s mouse position, after a few researches, I found this topic :
Code :
local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
local PlayerMouse = Player:GetMouse()
local Camera = workspace.CurrentCamera
local Character = Player.Character or Player.CharacterAdded:Wait()
local Head = Character:WaitForChild("Head")
local Neck = Head:WaitForChild("Neck")
local Torso = Character:WaitForChild("UpperTorso")
local Waist = Torso:WaitForChild("Waist")
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local NeckOriginC0 = Neck.C0
local WaistOriginC0 = Waist.C0
Neck.MaxVelocity = 1/3
RunService.RenderStepped:Connect(function()
local CameraCFrame = Camera.CoordinateFrame
if Character:FindFirstChild("UpperTorso") and Character:FindFirstChild("Head") then
local TorsoLookVector = Torso.CFrame.lookVector
local HeadPosition = Head.CFrame.p
if Neck and Waist then
if Camera.CameraSubject:IsDescendantOf(Character) or Camera.CameraSubject:IsDescendantOf(Player) then
local Point = PlayerMouse.Hit.p
local Distance = (Head.CFrame.p - Point).magnitude
local Difference = Head.CFrame.Y - Point.Y
Neck.C0 = Neck.C0:lerp(NeckOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * 0.5), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 1, 0), 0.5 / 2)
Waist.C0 = Waist.C0:lerp(WaistOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * 0.5), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 0.5, 0), 0.5 / 2)
end
end
end
end)
after trying to understand the code, I found it that I can’t understand well the algorithm by my own.
Why do we use :lerp() here and how can I understand the algorithm?
Well step one would be to format it better across multiple lines and probably breaking it out into more separate statements and variables. One liners like those are just pointlessly unreadable.
I’m guessing lerp is used to smooth out the movement in this case. Instead of snapping instantly to the right orientation it gradually moves there over time.
E.g.
b = a:lerp(c, 0.5)
sets b to be the halfway- value between a and c. If you put in 0 it’s 0% of the way from a to c (i.e. it’s just a), if you put it to 1 it’s 100% of the way so it’s just c. Lerp works on Vector3s and CFrames, and you can write a lerp function to work with plain numbers.
If you have a variable that is the desired CFrame, you can see how lerping results in gradual movement to the desired CFrame when this is done repeatedly:
Waist.C0 = Waist.C0:lerp(desiredWaitC0, 0.25)
Every time it moves C0 25% of the way to the desired C0. Over time it gets closer and closer.
First format it properly instead of all this one-liner stuff. Here I also added temporary comments just to show where the three angle components are calculated:
Now break it out into separate variables so the names say something about what each calculation is for. This simplifies some of the statements so much that it makes sense to put them back on single lines again:
local Pitch = -(math.atan(Difference / Distance) * 0.5)
local Yaw = (HeadPosition - Point).Unit:Cross(TorsoLookVector).Y
local TargetAngles = NeckOriginC0 * CFrame.Angles(Pitch, Yaw, 0)
Neck.C0 = Neck.C0:lerp(TargetAngles, 0.25)
Now it’s actually possible to see how the angle calculation is done, and making sense of it is just a matter of knowing the math. Drawing a diagram can be helpful here. Ask away if you’d like an explanation of the math that’s used here.
Yes please, an explanation would be useful for me. After searching the dev hub I still can’t under stand the math. (By the way sorry for disturbing you a lot of times )
Lerp is essentially something called Linear interpolation - Wikipedia, in it’s simplest form mathematics between it can be expressed with a number line.
Now we can actually represent an equation to give us a fraction between those two points. Which is… a+(b-a) * t -- Universal formula for 1D Linear interpolation
The variable t represents that fraction I was talking about.
Before explaining :lerp() I think showing an example would be nice, where t=1/2. (0)+( (1) - (0) ) * (1/2) -- Which equals 0.5
So :lerp() using what we know, is essentially linear interpolation on the CFrame coordinate of the object, which CFrame is the local position of the object on it’s own plane. It uses 3D and much more lengthy algorithm compared to the one I showed, but in simple terms, this is essentially what it is.