The lag only occurs when the player is firing. I’m trying to get other opinions about what might be causing the lag to occur and how to possibly correct it.
Client Code (Under StarterPlayerScripts)
--//SERVICES//
local Players = game:GetService('Players')
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local UserInputService = game:GetService('UserInputService')
--//VARIABLES//
local EVENTS = ReplicatedStorage['EVENTS']
local MODULES = ReplicatedStorage['MODULES']
local RENDER = EVENTS:WaitForChild('RENDER')
local GUNMOD = require(ReplicatedStorage.MODULES:WaitForChild('WEAPON'))
local LocalPlayer = Players.LocalPlayer
local Character = nil
local Humanoid = nil
local ingoreList = {}
local loadedAnimations = {}
local registeredWeapons = {}
local equippedWeapon = nil
local Equipped = false
local equippedWeaponInfo = {}
local equippedWeaponAnimations = {}
local equippedWeaponRegister = {}
local mouseDown = false
local canFire = true
local isFiring = false
local Reloading = false
local isHolstering = false
local weaponGUI = nil
local sprintBtn = nil
local crouchBtn = nil
local reloadBtn = nil
local processedFirstChar = false
local redIcon = 'rbxassetid://131718495'
local whiteIcon = 'rbxassetid://131581677'
local greenIcon = 'rbxassetid://131718487'
local crouchLoop
------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
--//FUNCTIONS
local function tk(plr, targetPlayer)
if plr.Team == game.Teams.Astria then
if targetPlayer.Team == game.Teams.Astria then
if plr:GetRankInGroup(3167990) < 80 then
return true
else
return false
end
else
return false
end
elseif plr.Team ~= game.Teams.Astria then
if targetPlayer.Team ~= game.Teams.Astria then
local plrTag
local targetTag
if plr.Character and targetPlayer.Character then
plrTag = plr.Character:FindFirstChild('Torso'):FindFirstChild('RANK'):FindFirstChild('RankFrame').Corporation
targetTag = targetPlayer.Character:FindFirstChild('Torso'):FindFirstChild('RANK'):FindFirstChild('RankFrame').Corporation
end
if plrTag ~= nil and targetTag ~= nil then
if plrTag.Visible == true and targetTag.Visible == true then
if plrTag.TextColor3 ~= targetTag.TextColor3 then
return false
else
return true
end
else
return true
end
else
return true
end
else
return false
end
end
end
local function loadAnimation(AnimationObj)
if not Character then return end
if loadedAnimations[AnimationObj] then return loadedAnimations[AnimationObj] end
local loadedAnimation = Humanoid:LoadAnimation(AnimationObj)
loadedAnimations[AnimationObj] = loadedAnimation
return loadedAnimation
end
local function newRay(TargetCFrame)
if Character and Character:FindFirstChild('Torso') then
local ray = Ray.new(Character:FindFirstChild('Torso').CFrame.p, (TargetCFrame.p - Character:FindFirstChild('Torso').CFrame.p).unit * 300)
return ray
end
end
local function getPartOnRay(ray)
if ray then
return workspace:FindPartOnRayWithIgnoreList(ray, ingoreList, false, true)
end
end
local function visualizeRay(targetPosition, overrideInfo)
overrideInfo = overrideInfo or {}
local rayDistance = ((overrideInfo.Origin or equippedWeapon.Barrel.CFrame.p) - targetPosition).magnitude
local Part = Instance.new('Part')
if overrideInfo and overrideInfo.Color then
Part.BrickColor = overrideInfo.Color
elseif LocalPlayer.Team == game.Teams.Astria then
Part.BrickColor = BrickColor.new('Steel blue')
elseif LocalPlayer.Team == game.Teams.Rebels then
Part.BrickColor = BrickColor.new('Dusty Rose')
else
Part.BrickColor = BrickColor.new('Institutional white')
end
Part.Material = overrideInfo.Material or Enum.Material.Neon
Part.Anchored = true
Part.CanCollide = false
Part.Locked = true
Part.FormFactor = Enum.FormFactor.Custom
Part.Size = Vector3.new(0.1,0.1,rayDistance)
Part.CFrame = CFrame.new(
overrideInfo.Origin or equippedWeapon.Barrel.CFrame.p,
overrideInfo.Target or targetPosition) * CFrame.new(0,0,-rayDistance/2)
Part.Parent = workspace
game:GetService('Debris'):AddItem(Part, .05)
end
local function getHumanoid(Object)
if not Object then return end
if Object.Parent:FindFirstChild('Humanoid') then
return Object.Parent.Humanoid
elseif Object.Parent.Parent:FindFirstChild('Humanoid') then
return Object.Parent.Parent.Humanoid
end
end
local function updateReticle(mouse)
if displayHit then
weaponGUI.Hit.Position = UDim2.new(0, mouse.X - 16, 0, mouse.Y - 16)
end
if mouse.Target then
if getHumanoid(mouse.Target) then
local targetPlayer
if Players:GetPlayerFromCharacter(Humanoid.Parent) then
targetPlayer = Players:GetPlayerFromCharacter(Humanoid.Parent)
end
if targetPlayer and not tk(LocalPlayer, targetPlayer) then
mouse.Icon = redIcon
else
mouse.Icon = whiteIcon
end
else
mouse.Icon = whiteIcon
end
end
end
local function animateCharacter(animationName)
if equippedWeaponRegister and equippedWeaponRegister.Animations and equippedWeaponRegister.Animations[animationName] then
equippedWeaponRegister.Animations[animationName]:Play()
end
end
local function stopSpecificAnimation(animationName)
if equippedWeaponRegister and equippedWeaponRegister.Animations and equippedWeaponRegister.Animations[animationName] then
equippedWeaponRegister.Animations[animationName]:Stop()
end
end
local function stopWeaponAnimations()
if not equippedWeaponRegister or not equippedWeaponRegister.Animations then return end
for i,v in pairs(equippedWeaponRegister.Animations) do
v:Stop()
end
end
local function playSound(soundName)
if equippedWeaponRegister and equippedWeaponRegister.Sounds and equippedWeaponRegister.Sounds[soundName] then
equippedWeaponRegister.Sounds[soundName]:Play()
end
end
--//TOGGLE SPRINT
local function holsterWeapon(newHolsterVal)
if newHolsterVal then
if Reloading or isFiring then return end
isHolstering = true
if Equipped then
stopSpecificAnimation('Idle')
animateCharacter('Ease')
end
if Humanoid and crouchLoop.IsPlaying then
Humanoid.HipHeight = 0
crouchLoop:Stop()
end
if Humanoid then
Humanoid.WalkSpeed = 24
end
else
isHolstering = false
animateCharacter('Idle')
stopSpecificAnimation('Ease')
Humanoid.WalkSpeed = 16
end
end
--//UPDATE UI
local function updateWeaponGUI()
if equippedWeapon and equippedWeaponRegister and equippedWeaponRegister.Ammo then
weaponGUI.Hud.Container.Display.Text = equippedWeaponRegister.Ammo..'/'..equippedWeaponInfo.Ammo
weaponGUI.Hud.Mode.Display.Text = 'Mode: ' .. equippedWeaponRegister.weaponType
weaponGUI.Hud.Weapon.Display.Text = equippedWeapon.Name
end
end
--//FIRE WEAPON
local function fireWeapon(mouse)
canFire = false
if equippedWeapon and Equipped and LocalPlayer.Character and LocalPlayer.Character:FindFirstChild('Head') then
local targetPosition = mouse.Hit.p
local rayDistance = (LocalPlayer.Character:FindFirstChild('Head') .Position - targetPosition).magnitude
local aimWithSpread = Vector3.new((targetPosition.x)+(math.random(-(equippedWeaponInfo.Spread/15)*rayDistance,(equippedWeaponInfo.Spread/15)*rayDistance)),(targetPosition.y)+(math.random(-(equippedWeaponInfo.Spread/15)*rayDistance,(equippedWeaponInfo.Spread/15)*rayDistance)),(targetPosition.z)+(math.random(-(equippedWeaponInfo.Spread/15)*rayDistance,(equippedWeaponInfo.Spread/15)*rayDistance)))
local ray = newRay(CFrame.new(aimWithSpread))
local hitPart,hitPosition = getPartOnRay(ray)
local visualRay = visualizeRay(hitPosition)
if hitPart then
local Humanoid = getHumanoid(hitPart)
if Humanoid then
local targetPlayer
if Players:GetPlayerFromCharacter(Humanoid.Parent) then
targetPlayer = Players:GetPlayerFromCharacter(Humanoid.Parent)
end
if targetPlayer and not tk(LocalPlayer, targetPlayer) then
weaponGUI.Hit.Visible = true
displayHit = true
weaponGUI.Hit.Position = UDim2.new(0,mouse.X-16,0,mouse.Y-16)
if weaponGUI:FindFirstChild('Hit') then
delay(0.1,
function()
if weaponGUI and weaponGUI:FindFirstChild('Hit') then
displayHit = false
weaponGUI.Hit.Visible = false
end
end)
end
end
end
local color
if LocalPlayer.Team == game.Teams.Astria then
color = BrickColor.new('Steel blue')
elseif LocalPlayer.Team == game.Teams.Rebels then
color = BrickColor.new('Dusty Rose')
else
color = BrickColor.new('Institutional white')
end
EVENTS.NETWORKING:FireServer('GunFire', equippedWeapon, hitPart, equippedWeapon.Barrel.Position, targetPosition, color)
end
end
spawn(function()
if equippedWeapon then
equippedWeapon.Barrel.Flash.Enabled = true
end
wait(0.1)
if equippedWeapon then
equippedWeapon.Barrel.Flash.Enabled = false
end
end)
playSound('Fire')
animateCharacter('Recoil')
equippedWeaponRegister.Ammo = equippedWeaponRegister.Ammo - 1
updateWeaponGUI()
wait(equippedWeaponInfo.Rate)
canFire = true
end
--//RELOAD WEAPON
local function reloadWeapon(Weapon)
if Reloading then return end
if isHolstering then
holsterWeapon(false)
end
canFire = false
Reloading = true
animateCharacter('Reload')
if Weapon.Name ~= 'KRM-1' then
playSound('MagOut')
end
playSound('Reload')
spawn(function()
for i = 1 ,3, 1 do
weaponGUI.Hud.Container.Display.Text = string.rep('.', i)
if equippedWeaponRegister.Animations then
wait(equippedWeaponRegister.Animations.Reload.Length/3)
end
end
end)
spawn(function()
wait(1)
playSound('MagIn')
wait(1)
playSound('Chamber')
end)
wait(equippedWeaponRegister.Animations.Reload.Length)
if not equippedWeapon == Weapon then return end
equippedWeaponRegister.Ammo = equippedWeaponInfo.Ammo
updateWeaponGUI()
Reloading = false
canFire = true
end
--//FIRE LOOP
local function fireLoop(mouse, Weapon)
if not canFire or not Equipped or not equippedWeapon == Weapon or Reloading or Humanoid.Health <= 0 or not equippedWeaponRegister then return end
if mouseDown then
if isHolstering then
holsterWeapon(false)
end
if equippedWeaponRegister and equippedWeaponRegister.weaponType == 'Auto' then
while mouseDown and Equipped and equippedWeapon == Weapon and equippedWeaponRegister.Ammo > 0 and canFire and not Reloading and Humanoid.Health > 0 do
isFiring = true
fireWeapon(mouse)
isFiring = false
end
elseif equippedWeaponRegister and equippedWeaponRegister.weaponType == 'Semi' and equippedWeaponRegister.Ammo > 0 then
isFiring = true
fireWeapon(mouse)
isFiring = false
end
if equippedWeaponRegister and equippedWeaponRegister.Ammo and equippedWeaponRegister.Ammo <= 0 then
playSound('EmptyMag')
reloadWeapon(Weapon)
end
end
end
--//EQUIP WEAPON
local function equipWeapon(mouse, Weapon)
if not registeredWeapons[Weapon] then warn('[RWEP] Tried to equip unregistered weapon') return end
if Humanoid.Health <= 0 then return end
equippedWeapon = Weapon
equippedWeaponInfo = registeredWeapons[Weapon].weaponInfo
equippedWeaponRegister = registeredWeapons[Weapon]
Equipped = true
weaponGUI.Hud.Container.Display.Text = equippedWeapon.Name
weaponGUI.Hud.Mode.Display.Text = registeredWeapons[Weapon].weaponType
weaponGUI.Hud.Visible = true
updateWeaponGUI()
if not equippedWeaponRegister.Animations['Idle'] then
local specificAnimations = GUNMOD[Weapon.Name].Anims
for i, v in pairs(specificAnimations) do
local anim = Instance.new('Animation')
anim.AnimationId = 'rbxassetid://' .. v
local loadedAnimation = loadAnimation(anim)
equippedWeaponRegister.Animations[i] = loadedAnimation
end
end
if not equippedWeaponRegister.Sounds['Fire'] then
for i,v in pairs(Weapon.Handle:GetChildren()) do
if v:IsA('Sound') then
equippedWeaponRegister.Sounds[v.Name] = v
end
end
end
animateCharacter('Idle')
mouse.Button1Down:Connect(function()
mouseDown = true
fireLoop(mouse, Weapon)
end)
mouse.Button1Up:Connect(function()
mouseDown = false
end)
mouse.Move:Connect(function()
updateReticle(mouse)
end)
end
--//UNEQUIP WEAPON
local function unequipWeapon()
if Humanoid.Health <= 0 then return end
Humanoid.WalkSpeed = 16
stopWeaponAnimations()
Equipped = false
isFiring = false
Reloading = false
canFire = true
equippedWeapon = nil
equippedWeaponInfo = {}
equippedWeaponRegister = {}
weaponGUI.Hud.Visible = false
end
--//REGISTER WEAPONS
local function registerWeapon(Weapon)
if registeredWeapons[Weapon] then return end
local localWeaponInfo = GUNMOD[Weapon.Name]
if localWeaponInfo then
local color
if LocalPlayer.Team == game.Teams.Astria then
color = BrickColor.new('Steel blue')
elseif LocalPlayer.Team == game.Teams.Rebels then
color = BrickColor.new('Dusty Rose')
else
color = BrickColor.new('Institutional white')
end
Weapon:WaitForChild('Barrel'):WaitForChild('Flash').Color = ColorSequence.new(color.Color)
local equippedConnection = Weapon.Equipped:Connect(function(mouse)
equipWeapon(mouse, Weapon)
end)
local unequippedConnection = Weapon.Unequipped:Connect(unequipWeapon)
registeredWeapons[Weapon] = {
['equippedConnection'] = equippedConnection;
['unequippedConnection'] = unequippedConnection;
['Ammo'] = localWeaponInfo.Ammo;
['weaponInfo'] = localWeaponInfo;
['weaponType'] = localWeaponInfo.Mode;
['Animations'] = {};
['Sounds'] = {};
}
end
end
--//NEW CHARACTER ADDED
local function processNewChar(newCharacter)
loadedAnimations = {}
registeredWeapons = {}
local Backpack = LocalPlayer:WaitForChild('Backpack')
local PlayerGui = LocalPlayer:WaitForChild('PlayerGui')
Character = newCharacter
Humanoid = newCharacter:WaitForChild('Humanoid')
ingoreList = {}
table.insert(ingoreList, Character)
table.insert(ingoreList, workspace:WaitForChild('Ignore'):WaitForChild('VaultDoor'))
table.insert(ingoreList, workspace:WaitForChild('Ignore'))
local animation = Instance.new('Animation')
animation.AnimationId = 'rbxassetid://1890511540'
if Character and Humanoid then
crouchLoop = Humanoid:LoadAnimation(animation)
weaponGUI = PlayerGui:WaitForChild('GunUI')
Backpack.ChildAdded:Connect(function(Child)
if Child:IsA('Tool') then
registerWeapon(Child)
end
end)
Backpack.ChildRemoved:Connect(function(Child)
if Child:IsA('Tool') then
if Child.Parent == Character then return end
if registeredWeapons[Child] then
registeredWeapons[Child]['equippedConnection']:Disconnect()
registeredWeapons[Child]['unequippedConnection']:Disconnect()
registeredWeapons[Child] = nil
end
end
end)
Humanoid.Died:Connect(function()
Humanoid:UnequipTools()
for i,v in pairs(Backpack:GetChildren()) do
if registeredWeapons[v] then
registeredWeapons[v]['equippedConnection']:Disconnect()
registeredWeapons[v]['unequippedConnection']:Disconnect()
end
end
registeredWeapons = {}
equippedWeapon = nil
equippedWeaponInfo = {}
equippedWeaponRegister = {}
Equipped = false
end)
Humanoid.Jumping:Connect(function(state)
if state and crouchLoop.IsPlaying then
Humanoid.HipHeight = 0
Humanoid.WalkSpeed = 16
crouchLoop:Stop()
end
end)
for i,v in pairs(Backpack:GetChildren()) do
if v:IsA('Tool') then
if not registeredWeapons[v] then
registerWeapon(v)
end
end
end
end
sprintBtn = weaponGUI:WaitForChild('Hud'):WaitForChild('Mobile'):WaitForChild('Sprint'):WaitForChild('Button')
crouchBtn = weaponGUI:WaitForChild('Hud'):WaitForChild('Mobile'):WaitForChild('Crouch'):WaitForChild('Button')
reloadBtn = weaponGUI:WaitForChild('Hud'):WaitForChild('Mobile'):WaitForChild('Reload'):WaitForChild('Button')
if sprintBtn then
sprintBtn.MouseButton1Click:Connect(function()
if not isHolstering then
holsterWeapon(true)
else
holsterWeapon(false)
end
end)
end
if crouchBtn then
crouchBtn.MouseButton1Click:Connect(function()
if Equipped == true and Humanoid then
if not (crouchLoop.IsPlaying) then
holsterWeapon(false)
Humanoid.HipHeight = -.8
Humanoid.WalkSpeed = 9
crouchLoop:Play()
else
Humanoid.HipHeight = 0
Humanoid.WalkSpeed = 16
crouchLoop:Stop()
end
end
end)
end
if reloadBtn then
reloadBtn.MouseButton1Click:Connect(function()
if Equipped and equippedWeaponRegister and equippedWeaponInfo and equippedWeaponRegister.Ammo < equippedWeaponInfo.Ammo then
reloadWeapon(equippedWeapon)
end
end)
end
end
LocalPlayer.CharacterAdded:Connect(processNewChar)
--//RENDER REQUEST
local function handleRender(Target, Origin, Color, Raycount, Spread)
visualizeRay(Target, {Origin = Origin, Color = Color})
end
RENDER.OnClientEvent:Connect(handleRender)
--//USER INPUT
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
if gameProcessedEvent then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
if input.KeyCode == Enum.KeyCode.R and not Reloading then
if Equipped and equippedWeaponRegister.Ammo < equippedWeaponInfo.Ammo then
reloadWeapon(equippedWeapon)
end
elseif input.KeyCode == Enum.KeyCode.F then
if not isHolstering then
holsterWeapon(true)
else
holsterWeapon(false)
end
elseif input.KeyCode == Enum.KeyCode.C then
if Equipped == true and Humanoid then
if not (crouchLoop.IsPlaying) then
holsterWeapon(false)
Humanoid.HipHeight = -.8
Humanoid.WalkSpeed = 9
crouchLoop:Play()
else
Humanoid.HipHeight = 0
Humanoid.WalkSpeed = 16
crouchLoop:Stop()
end
end
end
elseif (input.UserInputType == Enum.UserInputType.Gamepad1 and input.KeyCode == Enum.KeyCode.ButtonL2) then
if not isHolstering then
holsterWeapon(true)
else
holsterWeapon(false)
end
elseif (input.UserInputType == Enum.UserInputType.Gamepad1 and input.KeyCode == Enum.KeyCode.DPadRight) then
if Equipped and equippedWeaponRegister.Ammo < equippedWeaponInfo.Ammo then
reloadWeapon(equippedWeapon)
end
elseif (input.UserInputType == Enum.UserInputType.Gamepad1 and input.KeyCode == Enum.KeyCode.DPadLeft) then
if Equipped == true and Humanoid then
if not (crouchLoop.IsPlaying) then
holsterWeapon(false)
Humanoid.HipHeight = -.8
Humanoid.WalkSpeed = 9
crouchLoop:Play()
else
Humanoid.HipHeight = 0
Humanoid.WalkSpeed = 16
crouchLoop:Stop()
end
end
end
end)