Fake ViewModel Arms being very choppy for zero reason

Hello, I’m currently working on my first ViewModel. I’m trying to add sway, and it’s pretty choppy and not smooth at all, I have zero clue why.

runs.RenderStepped:Connect(function()
	local mouseDelta = uis:GetMouseDelta()/50
	local swayX = math.clamp(mouseDelta.X, -0.3,0.3)
	local swayY = math.clamp(mouseDelta.Y, -0.3,0.3)
		
	local targetCF = CFrame.new()
		
	targetCF = targetCF:Lerp(CFrame.new(swayX, swayY, 0), 0.3)

	viewmodel:PivotTo(camera.CFrame * targetCF)
end)

Repost

It’s a problem with your implementation. The lerp is unneccessary as its basically just doing swayX * .3 and swayY * .3. Meaning that it isn’t being smoothed out. You should have a sway variable on top as a vector2, then lerp that with swayX and swayY. Then use that variable for the rotation.

The effect might also look better if you rotate it rather than just offsetting it.

You mean like this?

local sway = Vector2.new(0.3)
local targetCF = CFrame.new(swayX, swayY, sway)

Like this

local sway = Vector2.new()
runs.RenderStepped:Connect(function()
	local mouseDelta = uis:GetMouseDelta()/50
	local swayX = math.clamp(mouseDelta.X, -0.3,0.3)
	local swayY = math.clamp(mouseDelta.Y, -0.3,0.3)

    sway = sway:Lerp(Vector2.new(swayX, swayY), .1)
		
	local targetCF = CFrame.new()
		
	targetCF = targetCF:Lerp(CFrame.new(sway.X, sway.Y, 0), 0.3)

	viewmodel:PivotTo(camera.CFrame * targetCF)
end)

.3 might also be too much. Try lower numbers.

Thank you, now how would I go about also making it shake slightly when walking and sway when moving the camera?

You can detect if the player is walking by checking the magnitude of the character humanoid move direction, then go from there.

I know how to check if the player is walking, how would I both sway if the character is moving and moving their camera at the same time, wouldn’t one overwrite the other?

Make two cframes then multiply by them both.

So, I changed my script a tiny bit so that the player can’t look up, and it’s choppy again. I’m highly sure I’m doing something wrong but I just don’t see it so I thought you could help again.

It’s just in a function that I call right after changing the arm position moments earlier.

viewmodel:PivotTo(camera.CFrame * (targetCFrame * swayCFrame))
ArmHeight()
function ArmHeight()
	local MaxUpRotation = 5

	local targetcframe = workspace.CurrentCamera.CFrame
	local Pitch,_,_ = targetcframe:ToOrientation()

	Pitch = math.min(Pitch,math.rad(MaxUpRotation))
	
	local newpos = CFrame.new() * hrp.CFrame * CFrame.Angles(Pitch,0,0)

	viewmodel:PivotTo(newpos)
end

“CFrame.new” should be the viewmodels current cframe. Use GetPivot for that. Right now your sway is overriding the other one.

local newpos = viewmodel:GetPivot()
newpos = newpos * hrp.CFrame * CFrame.Angles(Pitch,0,0)

viewmodel:PivotTo(newpos)

as for the overriding, I tried combining them and it had a similar effect as the video

Tried lerping it, it worked then but was also choppy. So I tried to combine it and this is the result

local rotCFrame = ArmHeight()

viewmodel:PivotTo(camera.CFrame * (targetCFrame * swayCFrame) * rotCFrame)
function ArmHeight()
	local MaxUpRotation = 5  -- change to your likings (did nothing, 5 and 20 still the same)

	local targetcframe = workspace.CurrentCamera.CFrame
	local Pitch,_,_ = targetcframe:ToOrientation()

	Pitch = math.min(Pitch,math.rad(MaxUpRotation))
	
	local newpos = viewmodel:GetPivot()
	newpos = newpos:Lerp(hrp.CFrame * CFrame.Angles(Pitch,0,0), 1)

	return newpos
end

Sorry, I should’ve said to combine the swayCFrame and the other one.

The same thing is still happening, it’s just flying off.

local rotCFrame = ArmHeight()
	
swayCFrame = swayCFrame * rotCFrame

viewmodel:PivotTo(camera.CFrame * targetCFrame * swayCFrame)

Don’t use the viewmodel’s cframe.

aight I just turned it back to CFrame.new() and same thing happening

function ArmHeight()
	local MaxUpRotation = 5

	local targetcframe = workspace.CurrentCamera.CFrame
	local Pitch,_,_ = targetcframe:ToOrientation()

	Pitch = math.min(Pitch,math.rad(MaxUpRotation))
	
	local newpos = CFrame.new()
	newpos = newpos:Lerp(hrp.CFrame * CFrame.Angles(Pitch,0,0), 1)

	return newpos
end

You are using the humanoid root parts cframe. You should only need the angle.

Edit: Delete the “hrp.CFrame *”.

I’m sorry, can you show me what you mean because I’m not sure how to change it like you requested

1 Like

Alright well that just broke the script, the arms were supposed to behave normally but if I move my screen up they stop at a point, now I don’t even know how to explain it.

This is how I had it and what I wanted, this is how it is now

It’s almost like it’s reversed, but it’s really weird.

If its reversed then you can just make the pitch negative in CFrame.Angles

To make a variable negative just put a “-” before it, like a number. The math.abs makes it positive, then forces it to be negative, which isn’t what you want.