I am trying to make a smooth return to the original camera and hand position in a view model, but I can’t figure out how to scale a CFrame especially since its a 4x4 matrix. I am currently learning algebra 2 in school and have next to no knowledge of matrices let alone translating multiplication of matrices to code.
Here’s what I’m trying to do (similar to how you would scale a Vector3):
cf = cf * .75
However I am receiving an error in the console that says ‘invalid argument 2’. I have searched far and wide for a simple answer, but the closest thing I found was a function that is not really for scaling.
I’ll just give you the full thing to see where the values are coming from
--//Services
local rst = game:GetService("ReplicatedStorage")
local rs = game:GetService("RunService")
local ts = game:GetService("TweenService")
--//Player
local player = game:GetService("Players").LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hum = char.Humanoid or char:FindFirstChild("Humanoid")
local humR = char.HumanoidRootPart or char:FindFirstChild("HumanoidRootPart")
--//Stuff
local hand = rst.Hand:Clone()
local handOffset = CFrame.new(2, -2.5, -2.6) * CFrame.Angles(math.rad(96), math.rad(-292.5), math.rad(40))
--//Camera
local cam = workspace.CurrentCamera
local lastCamCF = cam.CFrame
local originalCamCF = cam.CFrame
hum.CameraOffset = Vector3.new(0, 2, 0)
--//Main
hand.Parent = workspace
local final = CFrame.new()
local sway = CFrame.new()
local mult = 3
local function update()
local rot = cam.CFrame:ToObjectSpace(lastCamCF)
local x,y,z = rot:ToEulerAngles()
sway = sway:Lerp(CFrame.new(-math.sin(y)*mult, 0, -math.sin(y)*mult), .02)
local offset = cam.CFrame:ToWorldSpace(handOffset)
hand.CFrame = offset * sway
lastCamCF = cam.CFrame
if hum.MoveDirection.Magnitude > 0 then
local now = os.clock()
local vel = humR.AssemblyLinearVelocity
local clamp = math.min(1, vel.Magnitude / hum.WalkSpeed)
local xR = math.sin(hum.WalkSpeed*now*.5)/ 40
local yR = math.abs(math.cos(hum.WalkSpeed*now*.5))/ -20
local x2 = math.sin(hum.WalkSpeed*now*.5) * 1.5
local y2 = math.abs(math.cos(hum.WalkSpeed*now*.5)) * 2
local zR = math.sin(hum.WalkSpeed*now*.5)/ 20
local x2R = math.sin(hum.WalkSpeed*now)/ 400
local bobble = CFrame.new(x2*clamp, y2*clamp, 0) * CFrame.Angles(x2R*clamp, 0, zR*clamp)
cam.CFrame = cam.CFrame:Lerp(cam.CFrame * bobble, .1)
local bobble2 = CFrame.new(0, yR*clamp, xR*clamp)
final = final:Lerp(sway * bobble2, .1)
hand.CFrame = hand.CFrame:ToWorldSpace(final)
else
hand.CFrame = offset * sway
cam.CFrame = cam.CFrame
end
end
I tried it, but it didn’t work, it gave me ‘invalid argument #1 (CFrame expected, got Vector3)’. I tried changing (exampleCFrame.Position * 0.75) to CFrame.new(cam.CFrame.Position*.75), but it just made it look weird. I’ve tried Vector3 conversion a lot, but it doesn’t want to cooperate.
I read the whole thing over and still did not understand what you are trying to do
Since trying to scale it down to 0,0,0 doesn’t work, or “looks weird”
have you tried lerping an empty cframe to the current cframe? (this would “scale” the rotation as well)
Just to make sure I understand the problem correctly, the camera should sway when walking, and smoothly transition to not swaying when not walking?
(I really don’t see what is wrong in the video…)
In that case it may be helpful to store the time() when the User was last walking, and use that as the t in your lerp
So I am assuming I understood your problem correctly???
outside of everything initialize
local previousWalkingTime : number = 0
then
local now = time() -- move it outside the if statement
if hum.MoveDirection.Magnitude > 0 then
previousWalkingTime = time()
-- do everything else
else
-- do normally
end
so now you can use t, which is the distance of now to when you are last walking local t = math.abs(time() - previousWalkingTime)
so you would basically tween toward the non walking cframe using t
you put t in the t slot of the lerp WalkingCFrame:Lerp(nonWalkingCFrame,t)
This? It does the same thing as when I started. Also, yes I am trying to do what you are describing
local previousWalkingTime : number = 0
local function update()
local rot = cam.CFrame:ToObjectSpace(lastCamCF)
local x,y,z = rot:ToEulerAngles()
sway = sway:Lerp(CFrame.new(-math.sin(y)*mult, 0, -math.sin(y)*mult), .02)
local offset = cam.CFrame:ToWorldSpace(handOffset)
hand.CFrame = offset * sway
lastCamCF = cam.CFrame
local now = time()
if hum.MoveDirection.Magnitude > 0 then
previousWalkingTime = time()
local vel = humR.AssemblyLinearVelocity
local clamp = math.min(1, vel.Magnitude / hum.WalkSpeed)
local xR = math.sin(hum.WalkSpeed*now*.5)/ 40
local yR = math.abs(math.cos(hum.WalkSpeed*now*.5))/ -20
local x2 = math.sin(hum.WalkSpeed*now*.5) * 1.5
local y2 = math.abs(math.cos(hum.WalkSpeed*now*.5)) * 2
local zR = math.sin(hum.WalkSpeed*now*.5)/ 20
local x2R = math.sin(hum.WalkSpeed*now)/ 400
local bobble = CFrame.new(x2*clamp, y2*clamp, 0) * CFrame.Angles(x2R*clamp, 0, zR*clamp)
cam.CFrame = cam.CFrame:Lerp(cam.CFrame * bobble, .1)
local bobble2 = CFrame.new(0, yR*clamp, xR*clamp)
final = final:Lerp(sway * bobble2, .1)
hand.CFrame = hand.CFrame:ToWorldSpace(final)
else
local t = math.abs(time() - previousWalkingTime)
hand.CFrame = offset * sway
local camRot = cam.CFrame.Rotation
cam.CFrame = cam.CFrame:Lerp(cam.CFrame, t)
end
end
local previousWalkingTime: number = 0
local function computeCFWhenWalking()
local vel = humR.AssemblyLinearVelocity
local clamp = math.min(1, vel.Magnitude / hum.WalkSpeed)
local xR = math.sin(hum.WalkSpeed * now * 0.5) / 40
local yR = math.abs(math.cos(hum.WalkSpeed * now * 0.5)) / -20
local x2 = math.sin(hum.WalkSpeed * now * 0.5) * 1.5
local y2 = math.abs(math.cos(hum.WalkSpeed * now * 0.5)) * 2
local zR = math.sin(hum.WalkSpeed * now * 0.5) / 20
local x2R = math.sin(hum.WalkSpeed * now) / 400
local bobble = CFrame.new(x2 * clamp, y2 * clamp, 0)
* CFrame.Angles(x2R * clamp, 0, zR * clamp)
local goalCamCF = cam.CFrame:Lerp(cam.CFrame * bobble, 0.1)
local bobble2 = CFrame.new(0, yR * clamp, xR * clamp)
final = final:Lerp(sway * bobble2, 0.1)
local goalHandCF = hand.CFrame:ToWorldSpace(final)
return goalCamCF, goalHandCF
end
local function computeCFWhenNotWalking()
local offset = cam.CFrame:ToWorldSpace(handOffset)
local goalHandCF = offset * sway
local camRot = cam.CFrame.Rotation
local goalCamCF = cam.CFrame:Lerp(cam.CFrame, t)
return goalCamCF, goalHandCF
end
local function update()
local rot = cam.CFrame:ToObjectSpace(lastCamCF)
local x, y, z = rot:ToEulerAngles()
sway = sway:Lerp(CFrame.new(-math.sin(y) * mult, 0, -math.sin(y) * mult), 0.02)
local offset = cam.CFrame:ToWorldSpace(handOffset)
hand.CFrame = offset * sway
lastCamCF = cam.CFrame
local now = time()
if hum.MoveDirection.Magnitude > 0 then
previousWalkingTime = time()
else
-- Standing still, no update to walking time
end
local t = math.abs(time() - previousWalkingTime)
local goalCamCFW, goalHandCFW = computeCFWhenWalking()
local goalCamCF, goalHandCF = computeCFWhenNotWalking()
cam.CFrame = goalCamCFW:Lerp(goalCamCF, t)
hand.CFrame = goalHandCFW:Lerp(goalHandCF, t)
end