Why does this animation script behave so weirdly

I am trying to make an aiming animation for my viewmodel but theres some weird behavior while aiming. Ill include the while script (its pretty long but ill note the important parts.)

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local LogService = game:GetService("LogService")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local connections = {}

local function setupViewModel()
	-- Destroy existing viewmodel if it exists
	if workspace.CurrentCamera:FindFirstChild("ViewModelM4A1") then
		workspace.CurrentCamera.ViewModelM4A1:Destroy()
	end

	-- Clone the viewmodel from ReplicatedStorage
	local viewmodel = ReplicatedStorage:WaitForChild("ViewModelM4A1"):Clone()
	viewmodel.Parent = workspace.CurrentCamera

	-- Get the Animator
	local animator = viewmodel:WaitForChild("Humanoid"):WaitForChild("Animator")
	local Ranimation = Instance.new("Animation")
	Ranimation.AnimationId = "rbxassetid://70861748308924" -- Replace with your animation ID
	local RanimationTrack = animator:LoadAnimation(Ranimation)
	local REanimation = Instance.new("Animation")
	REanimation.AnimationId = "rbxassetid://75044431701578" -- Replace with your animation ID 
	local REanimationTrack = animator:LoadAnimation(REanimation)
	REanimationTrack.Priority = Enum.AnimationPriority.Action4
	local REEanimation = Instance.new("Animation")
	REEanimation.AnimationId = "rbxassetid://128464121251452" -- Replace with your animation ID
	local REEanimationTrack = animator:LoadAnimation(REEanimation)
	REEanimationTrack.Priority = Enum.AnimationPriority.Action4
	local WalkAnimation = Instance.new("Animation")
	WalkAnimation.AnimationId = "rbxassetid://139335711700900" -- Replace with your animation ID
	local WalkAnimationTrack = animator:LoadAnimation(WalkAnimation)
	WalkAnimationTrack.Looped = true
	local Aimanimation = Instance.new("Animation")
	Aimanimation.AnimationId = "rbxassetid://77150387885043"
	local AimanimationTrack = animator:LoadAnimation(Aimanimation) -- important
	-- Function to stop all playing animations
	local function stopAllAnimations()
		for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
			track:Stop()
		end
	end
	local camera = workspace.CurrentCamera
	
	local function moveCameraUp()
		local currentCFrame = camera.CFrame
		local newCFrame = currentCFrame * CFrame.Angles(math.rad(0.8), 0, 0)
		camera.CFrame = newCFrame
	end

	-- Function to play the animations
	local function RecoilAnimation()
		stopAllAnimations()
		RanimationTrack:Play()
	end

	local function ReloadAnimation()
		stopAllAnimations()
		REanimationTrack.Priority = Enum.AnimationPriority.Action4
		REanimationTrack:Play()
	end

	local function ReloadEmptyAnimation()
		stopAllAnimations()
		REEanimationTrack:Play()
	end

	UserInputService.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton2 then -- Here its important
			AimanimationTrack:Play()
		end
	end)

	UserInputService.InputEnded:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton2 then -- same one there
			AimanimationTrack:Stop()
		end
	end)
	
	local M4A1Fire = game.ReplicatedStorage["M4A1 RE"]:WaitForChild("M4A1Fire")
	local ReloadM4A1NotEmpty = game.ReplicatedStorage["M4A1 RE"]:WaitForChild("ReloadM4A1NotEmpty")
	local ReloadM4A1Empty = game.ReplicatedStorage["M4A1 RE"]:WaitForChild("ReloadM4A1Empty")

	-- Function to handle walking animation
	local function updateWalkingAnimation()
		if character.Humanoid.MoveDirection.Magnitude > 0 then
			if not WalkAnimationTrack.IsPlaying then
				WalkAnimationTrack:Play()
			end
		else
			if WalkAnimationTrack.IsPlaying then
				WalkAnimationTrack:Stop()
			end
		end
	end

	-- Connect the walking animation update to the RenderStepped event
	local runConnection = RunService.RenderStepped:Connect(updateWalkingAnimation)

	local M4A1FireConnection = M4A1Fire.OnClientEvent:Connect(function() 
		moveCameraUp()
		RecoilAnimation()
	end)

	local M4A1ReloadNotEmptyConnection = ReloadM4A1NotEmpty.OnClientEvent:Connect(function() 
		ReloadAnimation()
	end)

	local ReloadM4A1EmptyConnection = ReloadM4A1Empty.OnClientEvent:Connect(function()
		ReloadEmptyAnimation()
	end)

	table.insert(connections, runConnection)
	table.insert(connections, M4A1FireConnection)
	table.insert(connections, M4A1ReloadNotEmptyConnection)
	table.insert(connections, ReloadM4A1EmptyConnection)
end

local tool = player.Backpack:WaitForChild("M4A1")

tool.Unequipped:Connect(function()
	for _, connection in connections do
		-- We verify that the connection isn't nil or already disconnected
		if connection then
			connection:Disconnect()
		end
	end

	-- Clean the table's memory pointers
	connections = {}
end)

local function onToolEquipped(tool)
	if tool.Name == "M4A1" then
		setupViewModel()
	end
end

-- Connect the tool equipped event
player.Character.ChildAdded:Connect(function(child)
	if child:IsA("Tool") then
		onToolEquipped(child)
	end
end)

-- Handle tool replacement
player.Character.ChildRemoved:Connect(function(child)
	if child:IsA("Tool") and child.Name == "M4A1" then
		setupViewModel()
	end
end)

Heres the behavior of it:


So it makes the vmodel not rotate, the animation gets overrided by lower priority ones, and sometimes makes the vmodel go in random places. Could anyone help?

1 Like

You have to add an aimpart into your viewmodel and set the camera subject to it specifically when you are aiming in. The reason it is doing this is because you are not supposed to rotate yourself whatsoever when aiming in. The aimpart always rotates with the direction you are looking towards.