My Fireball Script works fine in Studio but in game it sometimes glitches?!

I have this very frustrating problem with Fireball/Energy Ball projectile scripts. The thing is they work perfectly fine in roblox studio and honestly they work pretty well in game. But sometimes it does this random thing where while holding the ball of energy, it disappears and causes the welding to not destroy as intended. I’ve tried to fix this for a couple of months, trying literally everything that comes to mind. Here is the server script for creating the Fireball and attaching it to the player’s character:

local replicatedStorage = game:GetService(“ReplicatedStorage”)
local fireballConjureEvent = replicatedStorage.Events.FireballConjure
local fireballThrowEvent = replicatedStorage.Events.FireballThrow
local fireballPart = replicatedStorage:WaitForChild(“FireballPart”)
local sounds = replicatedStorage.Sounds

local currentAnimationTrack
local fireballInPlay = false
local fireball

– Function to reset the fireball state for the player
local function resetFireballState()
fireballInPlay = false
if fireball then
– Ensure any Weld attachments are removed
local weld = fireball:FindFirstChild(“FireballWeld”)
if weld then
weld:Destroy()
end

	-- Remove any lingering sounds
	for _, child in pairs(fireball:GetChildren()) do
		if child:IsA("Sound") then
			child:Destroy()
		end
	end

	-- Add the fireball to debris for cleanup
	game:GetService("Debris"):AddItem(fireball, 0)
	fireball = nil -- Set to nil after ensuring cleanup
end

end

– Connection to handle character respawn
local function onCharacterAdded(character)
resetFireballState() – Reset the fireball state for the player
end

– Set up the player to listen for character respawns
local function onPlayerAdded(player)
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character)
end)
end

– Connect player added event
game.Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in ipairs(game.Players:GetPlayers()) do
onPlayerAdded(player)
end

fireballConjureEvent.OnServerEvent:Connect(function(player)
if fireballInPlay and fireball then
resetFireballState() – Reset any lingering fireball
end

local character = player.Character or player.CharacterAdded:Wait()
if character and character.Name == "Alistair" and not fireballInPlay then
	fireballInPlay = true -- Set this to true immediately to prevent duplicate conjuring
	-- Load Alistair's animation
	local animator = character:FindFirstChild("Humanoid"):FindFirstChild("Animator")
	local fireballAnimation = Instance.new("Animation")
	fireballAnimation.AnimationId = "rbxassetid://86098413114865"
	local conjureAnimationTrack = animator:LoadAnimation(fireballAnimation)

	conjureAnimationTrack:Play()

	-- Create FireballPart and attach it to Alistair's hand
	fireball = fireballPart:Clone()
	fireball.Parent = workspace
	fireball.CFrame = character.RightHand.CFrame * CFrame.new(0, 0, 0)

	-- Attach "FireballStart" sound and play it
	local fireballStartSound = sounds.FireballStart:Clone()
	fireballStartSound.Parent = fireball
	fireballStartSound:Play()

	-- Create a Weld to attach the fireball to Alistair's hand
	local weld = Instance.new("Weld")
	weld.Part0 = character.RightHand
	weld.Part1 = fireball
	weld.Name = "FireballWeld"
	weld.C0 = CFrame.new(0, 0, 0)
	weld.Parent = character.RightHand

	conjureAnimationTrack:GetMarkerReachedSignal("Hold"):Connect(function()
		conjureAnimationTrack:AdjustSpeed(0)
	end)

	wait(5)

	fireballStartSound:Destroy()
	local fireTransformationSound = sounds.FireTransformation:Clone()
	fireTransformationSound.Parent = fireball
	fireTransformationSound:Play()

	conjureAnimationTrack:AdjustSpeed(1)
	currentAnimationTrack = conjureAnimationTrack
end

end)

fireballThrowEvent.OnServerEvent:Connect(function(player, targetPosition)
local character = player.Character
if character and character.Name == “Alistair” and fireballInPlay and fireball then
– Detach the fireball from Alistair’s hand
local weld = character.RightHand:FindFirstChild(“FireballWeld”)
if weld then
weld:Destroy()
print(“FIREBALL weld attachment has been destroyed.”)
else
warn(“WELD PART FOR FIREBALL NOT FOUND!!!”)
end

	fireball.CFrame = character.RightHand.CFrame * CFrame.new(0, 0, 0)

	local fireTransformationSound = fireball:FindFirstChild("FireTransformation")
	if fireTransformationSound then
		fireTransformationSound:Destroy()
	end
	local fireballLaunchSound = sounds.FireballLaunch:Clone()
	fireballLaunchSound.Parent = fireball
	fireballLaunchSound:Play()

	fireball.Anchored = false

	local direction = (targetPosition - fireball.Position).unit
	local velocity = Instance.new("BodyVelocity")
	velocity.Velocity = direction * 50
	velocity.MaxForce = Vector3.new(10000, 10000, 10000)
	velocity.Parent = fireball

	game:GetService("Debris"):AddItem(fireball, 5)

	local launchAnimation = Instance.new("Animation")
	launchAnimation.AnimationId = "rbxassetid://128069439618404"
	local launchAnimationTrack = character:FindFirstChild("Humanoid"):FindFirstChild("Animator"):LoadAnimation(launchAnimation)

	if currentAnimationTrack then
		currentAnimationTrack:Stop()
	end

	launchAnimationTrack:Play()
	launchAnimationTrack.Stopped:Wait()

	fireballInPlay = false
	fireball = nil
end

end)

Then here is the server script inside of the actually Fireball part for when it impacts something or someone:

local replicatedStorage = game:GetService(“ReplicatedStorage”)
local fireballExplosionPart = replicatedStorage:WaitForChild(“FireballExplosionPart”)
local sounds = replicatedStorage.Sounds – Assuming all sounds are in ReplicatedStorage > Sounds

– Detect when the fireball touches another object
script.Parent.Touched:Connect(function(hit)
– Ensure this only triggers once per fireball and not when touching “Alistair”
if not script.Parent:IsDescendantOf(workspace) then return end

-- Check if the touched part belongs to "MacyForcefield" collision group and ignore if true
if hit.CollisionGroup == "MacyForcefield" then
	return
end

-- Check if the touched part is part of "Alistair" and ignore if true
local character = hit:FindFirstAncestorOfClass("Model")
if character and character.Name == "Alistair" then
	return
end

-- Clone the explosion part and position it at the impact point
local explosionClone = fireballExplosionPart:Clone()
explosionClone.Parent = workspace
explosionClone.CFrame = script.Parent.CFrame -- Position at the point of impact

-- Add "FireballImpact" sound to explosion part and play it
local impactSound = sounds.FireballImpact:Clone()
impactSound.Parent = explosionClone
impactSound:Play()

-- Emit particles from the particle emitter inside the explosion part
local particleEmitter = explosionClone:FindFirstChildOfClass("ParticleEmitter")
if particleEmitter then
	particleEmitter.Rate = 100 -- Set emission rate
	particleEmitter:Emit(250) -- Emit a burst of particles
end

-- Check if the character has a Humanoid (indicating it's a target humanoid)
local humanoid = character and character:FindFirstChild("Humanoid")
if humanoid then
	-- Apply damage only if the target has a humanoid
	humanoid:TakeDamage(30)

	local TRagdoll = character:FindFirstChild("Ragdoll")
	if TRagdoll then
		TRagdoll.Value = TRagdoll.Value + 2 -- Activate ragdoll effect
		print("Ragdoll activated for target")
	else
		print("Ragdoll not found for target")
	end

	-- Apply backward force on the hit character
	local primaryPart = character:FindFirstChild("HumanoidRootPart") or character.PrimaryPart
	if primaryPart then
		local bodyVelocity = Instance.new("BodyVelocity")
		bodyVelocity.MaxForce = Vector3.new(5000, 5000, 5000) -- Adjusted force for subtle knockback
		bodyVelocity.Velocity = -primaryPart.CFrame.LookVector * 20 -- Small backward push
		bodyVelocity.Parent = primaryPart

		-- Remove the force after a short time
		game:GetService("Debris"):AddItem(bodyVelocity, 0.2)
	end
end

-- Clean up the explosion part after a short delay
game:GetService("Debris"):AddItem(explosionClone, 2) -- Adjust time as needed

-- Destroy the fireball itself
script.Parent:Destroy()

end)

and here is the Local Script for the specific character:

wait(10.2)

warn(“Fireball script has loaded.”)

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local mouse = player:GetMouse()
local replicatedStorage = game:GetService(“ReplicatedStorage”)
local fireballConjureEvent = replicatedStorage:WaitForChild(“Events”):WaitForChild(“FireballConjure”)
local fireballThrowEvent = replicatedStorage:WaitForChild(“Events”):WaitForChild(“FireballThrow”)
local isAnimating = false
local UserInputService = game:GetService(“UserInputService”)
local TweenService = game:GetService(“TweenService”)
local Camera = workspace.CurrentCamera

local cooldown = 20
local lastActivationTime = 0

local function setupGui()
– Wait for the GUI to load properly, 5
local alistairPowersGui = player:WaitForChild(“PlayerGui”):WaitForChild(“AlistairPowersGui”, 5)
local frame = alistairPowersGui:WaitForChild(“Frame”)
local TPButton = frame:WaitForChild(“FireballButton”)

-- Connect button press logic
TPButton.TouchTap:Connect(function()
	buttonPressed = true -- Button was pressed
end)

--print("GUI successfully set up")

end

– Function to activate the fireball animation
local function activateFireballAnimation()
local currentTime = tick()

if character.Name == "Alistair" and not isAnimating and (currentTime - lastActivationTime) >= cooldown then
	isAnimating = true
	lastActivationTime = currentTime

	-- Fire the event to conjure the fireball
	fireballConjureEvent:FireServer()

	-- Zoom in effect
	local originalFieldOfView = Camera.FieldOfView
	local zoomedFieldOfView = originalFieldOfView - 20
	local zoomTween = TweenService:Create(Camera, TweenInfo.new(0.5), {FieldOfView = zoomedFieldOfView})
	zoomTween:Play()
	zoomTween.Completed:Wait() -- Wait for the tween to finish

	-- Red color correction effect
	local colorCorrection = Instance.new("ColorCorrectionEffect")
	colorCorrection.Brightness = -0.2
	colorCorrection.Contrast = 5.5
	colorCorrection.Saturation = -0.5
	colorCorrection.TintColor = Color3.new(1, 0, 0) -- Red tint
	colorCorrection.Parent = Camera
	local redTweenIn = TweenService:Create(colorCorrection, TweenInfo.new(0.5), {Brightness = 0.3})
	redTweenIn:Play()
	redTweenIn.Completed:Wait()

	wait(0.1) -- Short wait for effect duration

	local redTweenOut = TweenService:Create(colorCorrection, TweenInfo.new(0.5), {Brightness = 0})
	redTweenOut:Play()
	redTweenOut.Completed:Wait()
	colorCorrection:Destroy() -- Cleanup

	-- Zoom back out
	local zoomOutTween = TweenService:Create(Camera, TweenInfo.new(0.5), {FieldOfView = originalFieldOfView})
	zoomOutTween:Play()
	zoomOutTween.Completed:Wait() -- Wait for the tween to finish
end

end

– Variable for target mode
local isTargeting = false

– Function to handle touch input and determine target position in the world using raycasting
local function onTouchInput(inputObject)
if not isTargeting then return end

if inputObject.UserInputType == Enum.UserInputType.Touch then
	local ray = Camera:ScreenPointToRay(inputObject.Position.X, inputObject.Position.Y)
	local targetPosition = ray.Origin + ray.Direction * 1000 -- Set a large distance for the ray
	fireballThrowEvent:FireServer(targetPosition) -- Fire the throw event with the raycast position
	isAnimating = false -- Allow reactivation
	isTargeting = false -- Exit targeting mode
end

end

– Function to handle PC left-click input
–local function onWorldClick(inputObject)
– if not isTargeting then return end

– if inputObject.UserInputType == Enum.UserInputType.MouseButton1 then
– local targetPosition = mouse.Hit.p – Get the position where the mouse clicked
– fireballThrowEvent:FireServer(targetPosition) – Fire the throw event with target position
– isAnimating = false – Allow reactivation
– isTargeting = false – Exit targeting mode
– end
–end

– Handling mouse click for fireball throw
local function onWorldClick()
if isTargeting then
local fireballPosition = mouse.Hit.p – Get the position where the mouse clicked
fireballThrowEvent:FireServer(fireballPosition) – Fire the throw event with target position
isAnimating = false – Allow reactivation after throw
isTargeting = false – Exit targeting mode
end
end

– Connect the mouse click event

– Key press detection for PC
– Key press detection for PC
local function onInputBegan(input, gameProcessed)
if gameProcessed then return end

if character.Name ~= "Alistair" then return end

if input.KeyCode == Enum.KeyCode.F and not isAnimating then
	activateFireballAnimation()
	
	-- Start listening for the left click to launch fireball
isTargeting = true 

warn("Target mode activated, click to launch.")

end

end

– Connect the input began event for PC
game:GetService(“UserInputService”).InputBegan:Connect(onInputBegan)

– Function to handle button press to activate targeting mode
local function onFireballButtonPressed()
if character.Name == “Alistair” and not isAnimating then
activateFireballAnimation()

	-- Start targeting mode
	isTargeting = true
	warn("Target mode activated, click to aim and throw the fireball.")
end

end

– Set up FireballButton for Mobile
local fireballButton = player.PlayerGui:WaitForChild(“AlistairPowersGui”):WaitForChild(“Frame”):WaitForChild(“FireballButton”)

– Debugging to check if the button is being found
if not fireballButton then
warn(“Fireball Button not found!”)
else
fireballButton.TouchTap:Connect(onFireballButtonPressed)
buttonPressed = true
end

– Reset the script when the player respawns
player.CharacterAdded:Connect(function(newCharacter)
character = newCharacter
isAnimating = false
lastActivationTime = 0
isTargeting = false – Reset targeting mode on respawn
buttonPressed = false
setupGui()

local alistairPowersGui = player:WaitForChild("PlayerGui"):WaitForChild("AlistairPowersGui", 5)
local frame = alistairPowersGui:WaitForChild("Frame")
local TPButton = frame:WaitForChild("FireballButton")

-- Connect button press logic
if UserInputService.TouchEnabled then
	-- Reconnect the TouchTap event to handle mobile button press
	TPButton.TouchTap:Connect(onFireballButtonPressed)
end

	-- Wait for the GUI to load properly, 5

	--print("GUI successfully set up")

end)

setupGui()

– Connect to user clicks to trigger targeting
UserInputService.InputBegan:Connect(function(inputObject)
if inputObject.UserInputType == Enum.UserInputType.MouseButton1 then
onWorldClick(inputObject)
elseif inputObject.UserInputType == Enum.UserInputType.Touch then
onTouchInput(inputObject)
end
end)

Like i said I can use this ability as much as I want in Studio and it never glitches. But in game it randomly destroys the fireball before it is launched. Then it bugs and keeps the attachment to the player when thrown so the player flies away with the fireball too. PLEASE PLEASE someone help me I’ve been trying to find this solution. I’m the sole creator/owner of my game and I want to make it as good as I possibly can. Thank you!