Help fixing my viewmodel script

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to make a viewmodel for mah gun

  2. What is the issue? Include screenshots / videos if possible!
    The viewmodel animation’s works fine the first time equipping the tool, but after that it just stops working. (the viewmodel still loads, just no animations)

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I tried so many things i forgor. i did look for solutions on the dev hub, didnt find anythin tho

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

ViewModelHandler

local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local plrHum: Humanoid = char:WaitForChild("Humanoid")
local plrRoot: BasePart = char:WaitForChild("HumanoidRootPart")
local plrAnimator: Animator = plrHum:WaitForChild("Animator")
local cam = workspace.CurrentCamera
local tool = script.Parent
local module = require(script.Parent.AnimModule)
local reloading = tool.Reloading
local debounce = tool.debounce
local ammo = tool.Ammo
local maxAmmo = tool.maxAmmo
local UIS = game:GetService("UserInputService")

local RenderSteppedConnection = nil
local Animator = nil
local Viewmodel = nil

-- Function to set tool transparency
local function setToolTransparency(transparent)
    for _, part in ipairs(tool:GetDescendants()) do
        if part:IsA("BasePart") then
            part.Transparency = transparent and 1 or 0
        end
    end
end

-- Function to properly disconnect the ViewModel and stop animations
local function disconnectViewmodel()
    -- Disconnect RenderStepped if connected
    if RenderSteppedConnection then
        RenderSteppedConnection:Disconnect()
        RenderSteppedConnection = nil
    end
    
    -- Stop any playing animations before destroying Animator
    if Animator then
        local tracks = Animator:GetPlayingAnimationTracks()
        for _, track in ipairs(tracks) do
            track:Stop()
        end
        Animator:Destroy()
        Animator = nil
    end

    -- Destroy the ViewModel to avoid glitches
    if Viewmodel then
        Viewmodel:Destroy()
        Viewmodel = nil
    end
end

-- Function to set up the ViewModel and Animator
local function setupViewmodel()
    -- Destroy any existing ViewModel and Animator to start fresh
    if Viewmodel then
        Viewmodel:Destroy()
        Viewmodel = nil
    end
    if Animator then
        Animator:Destroy()
        Animator = nil
    end

    -- Clone a new ViewModel from ReplicatedStorage
    Viewmodel = game:GetService("ReplicatedStorage"):WaitForChild("ViewModel"):Clone()
    Viewmodel.Parent = workspace
    Animator = Viewmodel.Humanoid:WaitForChild("Animator")
    Viewmodel:SetPrimaryPartCFrame(cam.CFrame)  -- Align the ViewModel with the camera

    -- Disable collisions and physics on ViewModel parts
    for _, v in Viewmodel:GetDescendants() do
        if v:IsA("BasePart") then
            v.CanCollide = false
            v.CanTouch = false
            v.CanQuery = false
        end
    end
end

-- Handle tool equipped
tool.Equipped:Connect(function()
    -- Clean up the previous Viewmodel and Animator if they exist
    disconnectViewmodel()

    -- Setup the new ViewModel and Animator
    setupViewmodel()

    -- Make the tool invisible when equipped
    setToolTransparency(true)

    -- Set up animations and springs for sway and bob
    local Spring = require(script:WaitForChild('SpringModule'))
    local SwaySpring = Spring.new()
    local BobSpring = Spring.new()

    local function Bob(addition)
        return math.sin(tick() * addition * 1.3) * 0.5
    end

    -- Play idle animation after slight delay
    task.wait(0.1)
    module.IdlePistol(Animator)

    -- Connect RenderStepped to update ViewModel movement
    RenderSteppedConnection = game:GetService("RunService").RenderStepped:Connect(function(dt)
        if game:GetService("Players"):GetPlayerFromCharacter(tool.Parent) then
            local Delta = UIS:GetMouseDelta()
            SwaySpring:shove(Vector3.new(-Delta.X / 500, Delta.Y / 500, 0))
            BobSpring:shove(Vector3.new(Bob(5), Bob(10), Bob(5)) / 10 * (plr.Character.PrimaryPart.Velocity.Magnitude) / 10)
            local UpdatedSway = SwaySpring:update(dt)
            local UpdatedBob = BobSpring:update(dt)

            -- Smoothly update ViewModel position relative to camera
            Viewmodel:PivotTo(
                cam.CFrame *
                CFrame.new(UpdatedSway.X, UpdatedSway.Y, 0) *
                CFrame.new(UpdatedBob.X, UpdatedBob.Y, 0) *
                CFrame.new(0, -1.5, 0) *
                CFrame.Angles(0, .025, 0)
            )
        end
    end)

    -- Handle shooting logic
    tool.Activated:Connect(function()
        if not debounce.Value and ammo.Value > 0 and not reloading.Value then
            module.StopShootPistol(Animator)
            module.ShootPistol(Animator)
            debounce.Value = true
            task.wait(0.35)
            debounce.Value = false
        elseif not debounce.Value and ammo.Value == 0 and not reloading.Value then
            module.StopShootPistol(Animator)
            module.ReloadPistol(Animator)
            debounce.Value = true
            reloading.Value = true
            task.wait(1.75)
            module.PullPistol(Animator)
            task.wait(0.5)
            debounce.Value = false
            reloading.Value = false
        end
    end)
end)

-- Handle tool unequipped
tool.Unequipped:Connect(function()
    -- Stop all animations and clean up when tool is unequipped
    if Animator then
        module.StopShootPistol(Animator)
        module.StopIdlePistol(Animator)
    end

    -- Disconnect and clean up ViewModel and Animator
    disconnectViewmodel()

    -- Reset tool transparency to make it visible again
    setToolTransparency(false)
end)

-- Handle reload key (R) input
UIS.InputBegan:Connect(function(input, gameProcessed)
    if input.KeyCode == Enum.KeyCode.R and not gameProcessed then
        if not debounce.Value and ammo.Value < maxAmmo.Value and not reloading.Value then
            module.StopShootPistol(Animator)
            module.ReloadPistol(Animator)
            debounce.Value = true
            reloading.Value = true
            task.wait(1.75)
            module.PullPistol(Animator)
            task.wait(0.5)
            debounce.Value = false
            reloading.Value = false
        end
    end
end)

The ModuleScript

local module = {}
local PistolIdle, PistolReload, PistolPull, PistolShoot = nil, nil, nil, nil

function module.IdlePistol(Animator)
	if not PistolIdle then
		PistolIdle = Animator:LoadAnimation(script.PistolIdle)
	end
	if Animator then
		PistolIdle:Play(.25)
	end
end

function module.StopIdlePistol(Animator)
	if not PistolIdle then
		PistolIdle = Animator:LoadAnimation(script.PistolIdle)
	end
	if Animator then
		PistolIdle:Stop(.25)
	end
end

function module.ReloadPistol(Animator)
	if not PistolReload then
		PistolReload = Animator:LoadAnimation(script.PistolReload)
		PistolReload.Priority = Enum.AnimationPriority.Action4
	end
	if Animator then
		PistolReload:Play(.25)
	end
end

function module.StopReloadPistol(Animator)
	if not PistolReload then
		PistolReload = Animator:LoadAnimation(script.PistolReload)
		PistolReload.Priority = Enum.AnimationPriority.Action4
	end
	if Animator then
		PistolReload:Stop(.25)
	end
end

function module.PullPistol(Animator)
	if not PistolPull then
		PistolPull = Animator:LoadAnimation(script.PistolPull)
		PistolPull.Priority = Enum.AnimationPriority.Action4
	end
	if Animator then
		PistolPull:Play(.2)
	end
end

function module.StopPullPistol(Animator)
	if not PistolPull then
		PistolPull = Animator:LoadAnimation(script.PistolPull)
		PistolPull.Priority = Enum.AnimationPriority.Action4
	end
	if Animator then
		PistolPull:Stop(.2)
	end
end

function module.ShootPistol(Animator)
	if not PistolShoot then
		PistolShoot = Animator:LoadAnimation(script.PistolShoot)
		PistolShoot.Priority = Enum.AnimationPriority.Action4
	end
	if Animator then
		PistolShoot:Play(.05)
	end
end

function module.StopShootPistol(Animator)
	if not PistolShoot then
		PistolShoot = Animator:LoadAnimation(script.PistolShoot)
		PistolShoot.Priority = Enum.AnimationPriority.Action4
	end
	if Animator then
		PistolShoot:Stop(.05)
	end
end

return module

image

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

2 Likes