How To Make Tool Follow Viewmodel Arms

So I made a viewmodel arms script for tools, works pretty nice.

How I coded it

It clones a viewmodel template from ReplicatedStorage, puts the shirts, pants, and body colors of the player onto the viewmodel, use RenderStepped to lock the viewmodel in the camera’s CFrame, clone the real tool onto the viewmodel and make the real one invisible to the client, then listen for animations and play it on the viewport.

One problem though, the actual gun/tool doesn’t follow the viewmodel.

Not really sure how to solve this. Help would be appreciated!


VIEWMODEL CODE:

local RNS = game:GetService("RunService")
local RS = game:GetService("ReplicatedStorage")
local PS = game:GetService("Players")
local PYS = game:GetService("PhysicsService")

local camera = workspace.CurrentCamera
local char: Model = script:FindFirstAncestorWhichIsA("Model") do
	char.Archivable = true
end
local player: Player = PS:GetPlayerFromCharacter(char)
local hum: Humanoid = char:WaitForChild("Humanoid")
local animator: Animator = hum:WaitForChild("Animator")
local modelHum: Humanoid = nil
local modelAnimator: Animator = nil
local connections = {}
local viewmodel = nil
local loaded = {}

connections[1] = player.CharacterAppearanceLoaded:Connect(function()
	viewmodel = RS.Viewmodel:Clone() do
		viewmodel.Parent = camera
		viewmodel.Name = "Viewmodel"
		viewmodel.PrimaryPart = viewmodel:WaitForChild("Head")
		
		modelHum = viewmodel:WaitForChild("Humanoid")
		modelAnimator = modelHum:WaitForChild("Animator")
		
		local blacklist = {"left leg", "right leg"}
		
		for _,v in ipairs(char:GetDescendants()) do
			if v:IsA("Shirt") or v:IsA("Pants") or v:IsA("BodyColors") then
				local clone = v:Clone() do
					clone.Parent = viewmodel
				end
			end
		end

		char.Archivable = false
		
		connections[1]:Disconnect()
	end
end)

connections[2] = RNS.RenderStepped:Connect(function()
	if viewmodel then
		viewmodel:SetPrimaryPartCFrame(camera.CFrame)
	end
end)

connections[3] = animator.AnimationPlayed:Connect(function(track)
	if loaded[track] or not modelHum or not modelAnimator then
		warn("i like crying")
		return
	end
	
	loaded[track] = modelAnimator:LoadAnimation(track.Animation)
	loaded[track]:Play()
	
	track.Stopped:Connect(function()
		loaded[track]:Stop()
		loaded[track] = nil
	end)
end)

connections[4] = char.DescendantAdded:Connect(function(obj)
	if obj:IsA("Weld") and obj.Name == "RightGrip" then
		task.wait()
		
		for _,v in ipairs(viewmodel:GetChildren()) do
			if v:IsA("Tool") or v:IsA("Weld") and v.Name == "RightGrip" then
				v:Destroy()
			end
		end
		
		local weld = obj:Clone() do
			weld.Parent = viewmodel
		end
		local tool = obj.Part1.Parent:Clone() do
			tool.Parent = viewmodel
			
			weld.Part0 = viewmodel[obj.Part0.Name]
			weld.Part1 = tool.Handle
		end
		
		for _,v in ipairs(obj.Part1.Parent:GetChildren()) do
			if v:IsA("BasePart") then
				v.LocalTransparencyModifier = 1
			end
		end
	end
end)
1 Like

Solved, I just decided to go with actually changing the CFrames of the arms towards the camera.