Is math.rad() having a presision error?

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.

1 Like

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

Nope, does not work. It still does this:

1 Like

interesting. :ToOrientation() should be the issue, it gives a slightly inaccurate angle. For me, I fixed it by changing it to EulerAngles.

Just making sure, the issue is the angles aren’t precise, correct?

Yes, that is true. :ToOrientation() should be the issue

Alright, after seeing your edit you can make the gun‘s CFrame be the camera‘s cframe then offsetting it so its at the side

Gun.CFrame = Camera.CFrame+Vector3.new(offset)

So you mean: set it to the camera’s CFrame, but add an opposite orientation to create a fake latency?

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

We cannot do that. If we change the value while the tween is tweening, it will just abort the tween.


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

edit: do you kinda get what I mean?

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.

oof, alright. Well im glad I could help!

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

2 Likes

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

We can’t do that because then when you move, the latency is clearly seen. But I know how to fix it (by skipping update ticks for rotation only).