Please take a look at this code (this code sets the position of a part to the camera’s position, but tweens it’s rotation using CFrames to avoid breaking welds):
-- this is a local script because we don't want others to see the floating hands
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local camera = game.Workspace.CurrentCamera
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local viewModel = Instance.new("Part")
local viewModelStorage = game.Workspace:WaitForChild("storages"):WaitForChild("client"):WaitForChild("viewModels")
viewModel.Transparency = 1
viewModel.CanCollide = false
viewModel.Name = "head"
viewModelStorage:ClearAllChildren()
viewModel.Parent = viewModelStorage
viewModel.Anchored = true
local pre = CFrame.Angles(0, 0, 0)
while true do
RunService.RenderStepped:Wait()
local camCframe = camera.CFrame
local orientedCframe = camCframe * pre
local currentX, currentY, currentZ = camCframe:ToOrientation()
local currentCframeAngles = CFrame.Angles(math.rad(currentX), math.rad(currentY), math.rad(currentZ))
local currentOrientedCframe = camCframe * currentCframeAngles
-- current position with last orientation
viewModel.CFrame = orientedCframe
-- current position with current orientation
TweenService:Create(
viewModel,
TweenInfo.new(
0.2,
Enum.EasingStyle.Linear
),
{
["CFrame"] = currentOrientedCframe
}
):Play()
pre = currentCframeAngles
end
However, the weapon (that is welded to the viewModel) keeps jittering:
The same is true for the view model (highlighted blue):
Is there a precision problem, or am I doing something wrong?
Edit: If this is not solvable, please suggest a different way that I can add rotation latency.
Its not math.rad(), I had a similar issue. :ToOrientation() I think is used differently. Replace it with CFrame:ToEulerAnglesYXZ and it should be 100% accurate
no, like basically do the same method (tweening the CFrame) but in order to match the camera’s Orientation, instead of finding the degrees in angles, just outright make the gun‘s CFrame the camera’s CFrame. After that, move the gun‘s position so it still has the same rotation as the camera, but we move it to like the side so its not covering the camera. If that makes sense
while true do
RunService.RenderStepped:Wait()
local camCframe = camera.CFrame
local currentOrientedCframe = camCframe+Vector3.new(0,-2,-2) — making the gun cframe be the camera’s cframe, but offsetting it so its by the right hand
-- current position with last orientation
viewModel.CFrame = orientedCframe
-- current position with current orientation
TweenService:Create(
viewModel,
TweenInfo.new(
0.2,
Enum.EasingStyle.Linear
),
{
["CFrame"] = currentOrientedCframe
}
):Play()
pre = currentCframeAngles
end
while true do
RunService.RenderStepped:Wait()
local camCframe = camera.CFrame
local orientedCframe = camCframe * pre
local currentX, currentY, currentZ = camCframe:ToOrientation()
local currentCframeAngles = CFrame.Angles(math.rad(currentX), math.rad(currentY), math.rad(currentZ))
local currentOrientedCframe = camCframe+Vector3.new(0,-2,-2) -- making the gun cframe be the camera’s cframe, but offsetting it so its by the right hand
-- current position with last orientation
viewModel.CFrame = orientedCframe
-- current position with current orientation
TweenService:Create(
viewModel,
TweenInfo.new(
0.2,
Enum.EasingStyle.Linear
),
{
["CFrame"] = currentOrientedCframe
}
):Play()
pre = currentCframeAngles
end
Still does not work. I give up on this method, I think I have a better one in my mind.
One thing I would try is maybe getting the raw rotation of the Camera CFrame, then multiplying it to the gun‘s CFrame
local CamCFrame = Camera.CFrame
local CameraRotation = CamCFrame-CamCFrame.Position — gets rid of the position so its 0,0,0
Gun.CFrame = CFrame.new(PositionOfGun)*CameraRotation — applies camera’s rotation to the position of the gun
Well, at least the precision problem is gone. However, the jitter stays. We can fix the jitter, but thanks for giving me an idea of what I need to be doing. I achieved what I wanted (I wanted a latency on the rotation, but wanted the positon to be instant):
-- this is a local script because we don't want others to see the floating hands
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local camera = game.Workspace.CurrentCamera
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local viewModel = Instance.new("Part")
local viewModelStorage = game.Workspace:WaitForChild("storages"):WaitForChild("client"):WaitForChild("viewModels")
viewModel.Transparency = 1
viewModel.CanCollide = false
viewModel.Name = "head"
viewModelStorage:ClearAllChildren()
viewModel.Parent = viewModelStorage
viewModel.Anchored = true
local last = CFrame.Angles(0, 0, 0)
while true do
RunService.RenderStepped:Wait()
local camCframe = camera.CFrame
local camPosition = camCframe.Position
local camRotation = camCframe - camPosition
viewModel.CFrame = CFrame.new(camPosition) * last
TweenService:Create(
viewModel,
TweenInfo.new(
0.1,
Enum.EasingStyle.Linear
),
{
CFrame = camCframe
}
):Play()
last = camRotation
end
The reason why its happening is because each renderstep happens every 0.016 sec, and the tween you have lasts every 0.1. What I would do is make a wait(0.1) instead of waiting for each renderstep. It won’t be noticeable