I am making a game with a lot of characters, and I need them all to use the least amount of memory as possible.
Vid:
(Left is the stats, Consumable is melee, gun script is range, and NPC handler is the NPC… handler)
any help is appreciated, even the smallest amount
Melee Script
function module:CreateMelee(T)
local Tool = T::Tool
local Character
local Player
local Humanoid
local AttackAnimation
local SoundsFolder = Tool:FindFirstChild("Sounds")
local SwingSound = SoundsFolder:FindFirstChild("Swing")
local HitSound = SoundsFolder:FindFirstChild("Hit")
local Settings = Tool:FindFirstChild("Settings")
local WeaponModule = require(Tool:FindFirstChild("WeaponSettings"))
local WeaponSettings = WeaponModule:Get()
local Cooldown = Settings:FindFirstChild("Cooldown"):: BoolValue
Tool:SetAttribute("Attacking", false)
local Connections = {}
local function hit(EnemyCharacter, Hitbox, Func)
HitSound:Play()
local EnemyHumanoid = EnemyCharacter:FindFirstChild("Humanoid")
EnemyHumanoid:SetAttribute("MeleeCancel", true)
task.delay(WeaponSettings.WEAPON_COOLDOWN, function()
EnemyHumanoid:SetAttribute("MeleeCancel", false)
end)
if EnemyHumanoid.Health > 0 then
EnemyHumanoid:TakeDamage(WeaponSettings.DAMAGE)
if WeaponSettings.MULTIPLE_TARGETS == false then
Hitbox:Destroy()
Func:Disconnect()
end
end
end
local function Check(Part:Part, Hitbox, Func)
local EnemyCharacter = Part.Parent
if EnemyCharacter and EnemyCharacter.Parent ~= Character.Parent then
local EnemyHumanoid = EnemyCharacter:FindFirstChild("Humanoid")
if EnemyHumanoid and EnemyHumanoid:GetAttribute("MeleeCancel") ~= true then
hit(EnemyCharacter, Hitbox, Func)
end
end
end
Connections[1] = Tool.Equipped:Connect(function()
local OldCharacter = nil
if Character then
OldCharacter = Character
end
Character = Tool.Parent
Player = game.Players:GetPlayerFromCharacter(Character)
Humanoid = Character:FindFirstChild("Humanoid")
if OldCharacter == nil or OldCharacter ~= Character then
AttackAnimation = Humanoid:LoadAnimation(Settings.Attack)
AttackAnimation.Priority = Enum.AnimationPriority.Action3
end
SwingSound.Parent = Humanoid.RootPart
HitSound.Parent = Humanoid.RootPart
end)
Connections[2] = Tool.Unequipped:Connect(function()
end)
Connections[3] = Tool.Activated:Connect(function()
if Cooldown.Value == false then
AttackAnimation:Play()
SwingSound:Play()
local Func
task.spawn(function()
task.wait(WeaponSettings.HITBOX_WAITTIME)
local Hitbox = CreateHitbox(WeaponSettings.HITBOX_SIZE,Humanoid.RootPart) -- creates a fresh part to act as a hitbox
Hitbox.CFrame = CFrame.new(Humanoid.RootPart.Position + (Humanoid.RootPart.CFrame.LookVector * WeaponSettings.HITBOX_DISTANCE),Humanoid.RootPart.Position)
Hitbox.Parent = workspace.DebrisHolder
Func = Hitbox.Touched:Connect(function(Part)
Check(Part, Hitbox, Func)
end)
for _, Part in pairs(Hitbox:GetTouchingParts()) do
Check(Part, Hitbox, Func)
end
task.wait(WeaponSettings.HITBOX_LIFETIME)
if Hitbox then
Hitbox:Destroy()
end
if Func then
Func:Disconnect()
end
end)
Cooldown.Value = true
task.wait(WeaponSettings.WEAPON_COOLDOWN)
Cooldown.Value = false
if Tool:GetAttribute("Attacking") == true then
Tool:Activate()
end
end
end)
Connections[4] = Tool.AttributeChanged:Connect(function(Attribute: string)
if Tool:GetAttribute("Attacking") == true then
Tool:Activate()
end
end)
Connections["Final"] = Tool.Destroying:Connect(function()
for _, connection in Connections do
connection:Disconnect()
end
end)
end
Gun script (the main things that eat memory):
function module:MakeFireFX(Attachment)
for _, Effect: ParticleEmitter in pairs(Attachment:GetChildren()) do
Effect.Parent = Attachment
Effect:Emit(Effect:GetAttribute("EmitCount"))
end
end
function module:PlayFolderSound(Folder,Location)
for _, Sound in pairs(Folder:GetChildren()) do
local NewSound = Sound:Clone():: Sound
NewSound.Parent = Location
local OriginalSpeed = NewSound.PlaybackSpeed * 10
NewSound.PlaybackSpeed = math.random(OriginalSpeed - 1,OriginalSpeed + 1) * .1
NewSound:Play()
Debris:AddItem(NewSound, NewSound.TimeLength)
end
end
function module:OnRayHit(cast, raycastResult)
-- This function will be connected to the Caster's "RayHit" event.
local hitPart = raycastResult.Instance
local hitPoint = raycastResult.Position
local normal = raycastResult.Normal
if hitPart ~= nil and hitPart.Parent ~= nil then -- Test if we hit something
local HitCharacter = hitPart.Parent
local humanoid = HitCharacter:FindFirstChild("Humanoid")
if humanoid then
if HitCharacter.Parent == self.Character.Parent then
return
end
local Health = humanoid.Health
if hitPart.Name == "Head" then
humanoid:TakeDamage(self.Settings.DAMAGE * self.Settings.HEADSHOT_MULTIPLIER)
else
humanoid:TakeDamage(self.Settings.DAMAGE)
end
end
--self:explodeBullet(hitPoint)
--module.MakeParticleFX(hitPoint, normal) -- Particle FX
end
end
NPC script (This Fires every .25 seconds):
for PosTable, Table in ListOfNPCS do
task.spawn(function()
local Character: Model = Table[1]
local CharacterPathfinding = Table[2]
local OtherThings = Table[3]
local Tool = Character:FindFirstChildWhichIsA("Tool")
local Humanoid: Humanoid = Character:FindFirstChild("Humanoid")
local PercentageOfHealth = Humanoid.Health / Humanoid.MaxHealth
local RootPart = Humanoid.RootPart
local AlignOrientation: AlignOrientation = OtherThings.AlignOrientation
local WeaponSettings = OtherThings.WeaponSettings
local CharacterInfo = OtherThings.CharacterInfo
local AbilityModule = OtherThings["AbilityModule"]
if Humanoid.Health <= 0 then
table.remove(ListOfNPCS, PosTable)
CustomClassModule.getClass("NPC").new().Create(Tool.Name, nil, Character.Parent)
Tool:SetAttribute("Firing", false)
task.spawn(function()
task.wait(.5)
Character:Destroy()
end)
return
end
if WeaponSettings == nil then
OtherThings.WeaponSettings = require(Tool.WeaponSettings)
WeaponSettings = OtherThings.WeaponSettings
end
if AbilityModule == nil and Humanoid:FindFirstChild("Ability") then
OtherThings.AbilityModule = require(Humanoid:FindFirstChild("Ability"))
AbilityModule = OtherThings["AbilityModule"]
OtherThings.Ability = {
["Cooldown"] = 0,
["Info"] = AbilityModule:GetAbilityInfo(),
}
elseif Humanoid:FindFirstChild("Ability") == nil then
AbilityModule = false
end
if AbilityModule ~= false then
local AbilityCD = OtherThings.Ability.Cooldown
if AbilityCD > 0 then
OtherThings.Ability.Cooldown -= .25
AbilityCD = OtherThings.Ability.Cooldown
end
if AbilityCD <= 0 and CheckAbility(OtherThings.Ability.Info,Character) then
AbilityModule:UseAbility()
OtherThings.Ability.Cooldown = OtherThings.Ability.Info.Cooldown
end
end
local Target: Model = GetNearestTarget(RootPart, CharacterInfo.Range, Character.Parent)
--[[Tool:SetAttribute("Firing", true)
Tool:SetAttribute("AimPos", RootPart.Position + Vector3.new(0,-10,75))]]
if Target then
local TargetRootPart = Target:FindFirstChild("HumanoidRootPart")
local Distance = GetDistanceFromPos(RootPart.Position, TargetRootPart.Position)
if AlignOrientation.Enabled == false then
AlignOrientation.Enabled = true
end
AlignOrientation.CFrame = CFrame.lookAt(RootPart.Position, TargetRootPart.Position)
if CharacterInfo.CombatType == 'Ranged' then
if Distance > CharacterInfo.Range then
Tool:SetAttribute("Attacking", false)
CharacterPathfinding:Run(TargetRootPart)
else
Tool:SetAttribute("Attacking", true)
Tool:SetAttribute("AimPos", TargetRootPart.Position)
local Retreat = false
if Distance < CharacterInfo.RetreatZone then
Retreat = true
end
if Retreat == true or PercentageOfHealth < .5 then
Humanoid.WalkToPoint = RootPart.Position + -(RootPart.CFrame.LookVector * 6)
else
Humanoid.WalkToPoint = RootPart.Position + Vector3.new(math.random(-3,3),0,math.random(-3,3))
end
end
else
Humanoid:MoveTo(TargetRootPart.Position)
if Distance < CharacterInfo.MeleeRange then
Tool:SetAttribute("Attacking", true)
else
Tool:SetAttribute("Attacking", false)
end
end
else
Tool:SetAttribute("Attacking", false)
AlignOrientation.Enabled = false
CharacterPathfinding:Run(workspace.MovePart)
end
end)
end