ViewModel gun sway is working, but the ViewModel Floats in air

I know I already made 2 topics about ViewModels, but now I have it working how I wanted it to work. Also I have one last issue which has me stuck. I have got the ViewModel to sway like a FPS, but the ViewModel is floating in the air. I’m also using EgoMoose’s FPS tutorial system

local humanoid = game.Players.LocalPlayer.CharacterAdded:Wait():WaitForChild("Humanoid");
local hrp = game.Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart");

local remoteEvents = game.ReplicatedStorage:WaitForChild("RemoteEvents");

local viewModel = game.ReplicatedStorage:WaitForChild("viewModel"):Clone();
local repWeapon = game.ReplicatedStorage:WaitForChild("M249");
local weapon = repWeapon:Clone();

-- setup

weapon.Parent = viewModel;
viewModel.Parent = camera;

local joint = Instance.new("Motor6D");
joint.C0 = CFrame.new(1, -1.5, -2);
joint.Part0 = viewModel.Head;
joint.Part1 = weapon.Handle;
joint.Parent = viewModel.Head;

local aimCount = 0;
local offset = weapon.Handle.CFrame:inverse() * weapon.Aim.CFrame;

remoteEvents.setup:FireServer(repWeapon);

wait();
local holdAnim = humanoid:LoadAnimation(repWeapon.HoldAnim);
local aimAnim = humanoid:LoadAnimation(repWeapon.AimAnim);
local lastAnim = holdAnim;
lastAnim:Play();

-- functions

local function updateArm(key)
	local shoulder = viewModel[key.."UpperAr"][key.."Shoulder"];
	local cf = weapon[key].CFrame * CFrame.Angles(math.pi/2, 0, 0) * CFrame.new(0, 1.5, 0);
	shoulder.C1 = cf:inverse() * shoulder.Part0.CFrame * shoulder.C0;
end

local function aimDownSights(aiming)
	local start = joint.C1;
	local goal = aiming and joint.C0 * offset or CFrame.new();
	
	lastAnim:Stop();
	lastAnim = aiming and aimAnim or holdAnim;
	lastAnim:Play();
	
	aimCount = aimCount + 1;
	local current = aimCount;
	for t = 0, 101, 10 do
		if (current ~= aimCount) then break; end
		game:GetService("RunService").RenderStepped:Wait();
		joint.C1 = start:Lerp(goal, t/100);
	end
end

-- events

local function onDied()
	viewModel.Parent = nil;
end

local function onUpdate(dt)
	viewModel.Head.CFrame = camera.CFrame;
	updateArm("Right");
	updateArm("Left");
end

local function onInputBegan(input, process)
	if (process) then return; end
	if (input.UserInputType == Enum.UserInputType.MouseButton2) then
		aimDownSights(true);
	end
end

local function onInputEnded(input, process)
	if (process) then return; end
	if (input.UserInputType == Enum.UserInputType.MouseButton2) then
		aimDownSights(false);
	end
end

local runcf = camera.CFrame;

local function sprint(actionName, inputState, inputObject)
	if inputState == Enum.UserInputState.Begin then
				runcf = runcf:lerp(CFrame.new() * CFrame.Angles(math.rad(-20),math.rad(20),math.rad(20)),.1)
				game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 20
			else
				runcf = runcf:lerp(CFrame.new(),.1)
				game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 16
	end
end

local walkanimcf = joint.C0; -- the start of issue

game:GetService("RunService").RenderStepped:Connect(function()
			viewModel:SetPrimaryPartCFrame( -- I have Head as PrimaryPart
				walkanimcf
			)
end)

game:GetService("RunService").RenderStepped:Connect(function()
local speed = game.Players.LocalPlayer.Character.Humanoid.WalkSpeed/16

			walkanimcf = walkanimcf:lerp(
				CFrame.Angles(
					
					0,
					0,
					-.02 * math.sin(tick() * (2 * speed))
				
				)
			,.5)
end) -- the end of issue

-- connections

humanoid.Died:Connect(onDied);
game:GetService("RunService").RenderStepped:Connect(onUpdate);
game:GetService("UserInputService").InputBegan:Connect(onInputBegan);
game:GetService("UserInputService").InputEnded:Connect(onInputEnded);
game:GetService("ContextActionService"):BindAction("Run", sprint, true, Enum.KeyCode.LeftShift)

while (true) do
	wait(0.1);
	remoteEvents.tiltAt:FireServer(math.asin(camera.CFrame.LookVector.y));
end```

This doesn’t tell me much. Could you provide a gif?

42gqyv

The GIF you provided is too small for me to get anything from it. Could you post a new GIF using Gyazo or similar with an explanation of what’s not working as you’re wanting it to?

https://gyazo.com/56a599b01d2f824c696d11642f41be58

You shouldn’t weld the ViewModel if that’s what you’ve done. Rather just set the HumanoidRootPart’s CFrame to the camera’s with an offset of course.

The ViewModel doesn’t have a HumanoidRootPart.

Then the same would apply for whatever you have set as the PrimaryPart (not using :SetPrimaryPart!) or the “Root” part which everything is connected to.

I already have the PrimaryPart set to the camera’s CFrame

so what should I do?

You’re seemingly updating the ViewModel twice. Once by setting the primary part CFrame using the function, and one where you set the Head’s CFrame.

In addition, there’s no point in connecting to the .RenderStepped event multiple times for what you’re trying to achieve here. Try and reduce the amount of times you connect to the .RenderStepped event to only once.

Still doesn’t work after I did what you said. Can you please show me an example of what what the script would look like?

hello, I have a similar problem with the same egomoose system, I wanted to add animations to the viewmodel but I realized that the arms were practically welded to two reference blocks found in the weapon model called left and right.
I tried to disconnect them but this led me to more problems since when disconnecting the reference blocks with my hands the viewmodel simply did not move, not even to aim and I realized something else and that is that the blocks are welded to the weapon, thus making the weapon the only thing that moves.
any way to make the view model follow the camera and also when pointing and being able to make animations without having the reference blocks?.