Choppy Sway Animation

I want to have a good sway animation, however it looks really choppy, even with the change to the alpha. How would I make it look more smoother and maybe even give it wobble?

if config then
	local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF)
	local x,y,z = rotation:ToOrientation() 
	swayOffset = swayOffset:Lerp(CFrame.new(0,config.CameraOffset.Value,0) * CFrame.Angles(math.sin(x)*config.Sway.Value,math.sin(y)*config.Sway.Value,0), 0.05)
	viewmodel.HumanoidRootPart.CFrame = lastCameraCF * swayOffset
	lastCameraCF = workspace.CurrentCamera.CFrame --update the last cframe
end

1 Like

Try using RunService.RenderStepped e.g:

local RunService = game:GetService("RunService")

RunService.RenderStepped:Connect(function ()
	if config then
		local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF)
		local x,y,z = rotation:ToOrientation() 
		swayOffset = swayOffset:Lerp(CFrame.new(0,config.CameraOffset.Value,0) * CFrame.Angles(math.sin(x)*config.Sway.Value,math.sin(y)*config.Sway.Value,0), 0.05)
		viewmodel.HumanoidRootPart.CFrame = lastCameraCF * swayOffset
		lastCameraCF = workspace.CurrentCamera.CFrame --update the last cframe
	end
end)

This should help :wink:

Quick note:
Don’t forget to add delta time functionality for stuff like this.

local RunService = game:GetService("RunService");

-- A speed value of 3 gives 0.05 at 60 fps; Start:Lerp(Goal, Speed * Delta)
local Speed = 3; -- adjust to liking. Lerp equation: Speed * DeltaTime
-- Rough estimate: 60 * (1/60 (fps)) == 1 or 30 * (1/60) == 0.5 (for speed estimation)
-- For 0.05 lerp speed you'd want a speed value of roughly 3.

RunService.RenderStepped:Connect(function(Delta) -- Delta: time between frames
	if config then
		local rotation = workspace.CurrentCamera.CFrame:toObjectSpace(lastCameraCF);
		local x, y, z = rotation:ToOrientation();
		swayOffset = swayOffset:Lerp(CFrame.new(0, config.CameraOffset.Value, 0) * CFrame.Angles((math.sin(x) * config.Sway.Value), (math.sin(y) * config.Sway.Value), 0), Speed * Delta);
		viewmodel.HumanoidRootPart.CFrame = lastCameraCF * swayOffset;
		lastCameraCF = workspace.CurrentCamera.CFrame;
	end;
end);
1 Like

I did, didn’t include the rest.

It doesn’t really fix the choppy sway. I already have the renderstepped and everything.

Could you please include a bit more of the script? Thanks.

its rounding because you’re using :Lerp(). its not late/not updating fast enough, the mathematical results being produced are not precise and they’re inbetweens (interpolated) whereas it’d be better if you just had the cframe on a small delay like a few frames behind or even just make it a physics object and use alignorientation with some dampening to its force

alignorientation here would be on your viewmodel. i did this with a football game im making to allow the custom player model to follow the camera more smoothly (as its a physics based game) but i noticed it had nice applications to the viewmodel

AlignOrientation can be found here.

1 Like

ima keep adding answers as well

if you’re also just doing random sway, maybe just rig the viewmodel via motor6d’s (or just one) and use tweenservice to animate the motor6d orientation/cframe data so its always relative. makes it a lot easier and smoother

If you go to the link, I would recommend reading all the information they provide. Here is a piece of information you will read that is important to remember.

Link: RunService | Roblox Creator Documentation

If you look at the image, you can see that it is stated that the default control scripts use the ‘Input’ and ‘Camera’ render priorities.
So in your case, you will want to use BindToRenderStep and when setting the piority, I would set it to character. In other situations, it is recommended that if other localscripts are using the same priority, is simply subtract a value from the priority value anywhere from 1-99. Just like the ZIndex property on frames. The lower the number, the faster they run compared to other functions used with binding to render step.

I was recently working on a Fps system as well and I believe you are having the same issues as I had. I will post again later with how I apply sway to my Fps system

Delta time will always differ from frame to frame, and so will previous camera position in relation to the current. Contrary to what people write in this thread, if you use previous camera position/rotation or deltaTime * Speed (or deltaTime * literally any other value) to calculate new position of an object relative to the camera, you will unevetably see choppy movement. In my expecience majority of issues with choppy movement of objects in relation to the camera are caused by frametime.

The problem in your code is that you use previous camera rotation and your previous camera CFrame.
What you want to do instead is to only use values that are not multiplied by frametime. Speed and Acceleration, for example, are not affected by frametime randomness so you want to use them instead.
To implement sway I would calculate AngularVelocity and LinearVelocity using previous camera CFrame and frametime and use them instead (multiplied by some coefficient picked by hand so sway is not too intense). And of course make sure you don’t Lerp it using deltaTime.

1 Like

Would you provide an example? I don’t use velocities that often.

Hi, use stepped(and its delta time). Render stepped and heartbeat will cause it to be choppy. Make sure Adaptive time stepping is off that will also make it choppy. Also, I recommend using a spring for something like this that’s usually how people do gun sways. This seems to work already but springs will add a lot of customization like how fast you want it or how springy(the wobble you want).