I’m currently working on my first attempt at a personal-use module and I’m looking for some feedback on whether anything could be optimized
It uses a while loop so I already know that may not be the most efficient nor accurate method, but it works for the type of things I’ve used it for so far
Hitbox (Fix 2).rbxm (2.3 KB)
Initializing
local HitboxModule = require(ModuleScriptHere)
local hitboxObject = HitboxModule.new(BasePartHere)
Functions
hitboxObject:GetTouchingCharacters() -- returns table of characters inside hitbox
hitboxObject:GetTouchingPlayers() -- returns table of players inside hitbox
Events
hitboxObject.PlayerEntered (returns player) -- Fired when player enters
hitboxObject.PlayerExited (returns player) -- Fired when player exits
hitboxObject.CharacterEntered (returns character) -- Fired when character enters
hitboxObject.CharacterExited (returns character) -- Fired when character exits
Example
Here I give the player a forcefield when entering, and remove it when exiting
local HitboxModule = require(game.ReplicatedStorage.Hitbox)
local hitboxObject = HitboxModule.new(workspace.ExamplePart)
hitboxObject.PlayerEntered:Connect(function(player)
print(player, "entered the box")
local forceField = player.Character:FindFirstChildOfClass("ForceField")
if not forceField then
local forceField = Instance.new("ForceField")
forceField.Visible = true
forceField.Parent = player.Character
end
end)
hitboxObject.PlayerExited:Connect(function(player)
print(player, "exited the box")
local forceField = player.Character:FindFirstChildOfClass("ForceField")
forceField:Destroy()
end)
Module Script
-- CorruptionGhost
local Players = game:GetService("Players")
local Functions = require(script.Functions)
local Hitbox = {}
Hitbox.__index = Hitbox
-- [Constructor]
function Hitbox.new(hitboxPart : BasePart)
-- Checking BasePart
if not (hitboxPart:IsA("BasePart")) then
warn(script:GetFullName() .. ":", hitboxPart, "is not a valid BasePart")
return nil
end
-- Creating Object
local self = {}
setmetatable(self, Hitbox)
self.Part = hitboxPart
-- Creating Events
local PlayerEntered = Instance.new("BindableEvent")
self.PlayerEntered = PlayerEntered.Event
local PlayerExited = Instance.new("BindableEvent")
self.PlayerExited = PlayerExited.Event
local CharacterEntered = Instance.new("BindableEvent")
self.CharacterEntered = CharacterEntered.Event
local CharacterExited = Instance.new("BindableEvent")
self.CharacterExited = CharacterExited.Event
-- Detecting Character Enter/Exit (While Loop Coroutine)
self.Active = true
local hitboxCoroutine = coroutine.create(function()
local player;
local previouslyTouching = self:GetTouchingCharacters()
local currentlyTouching = {}
local tableDifference = true
local charactersEntered;
local charactersExited;
while self.Active do
currentlyTouching = self:GetTouchingCharacters()
charactersEntered = Functions.ExclusiveInTable(currentlyTouching, previouslyTouching)
for _, character in pairs(charactersEntered) do
CharacterEntered:Fire(character)
player = Players:GetPlayerFromCharacter(character)
if player then
PlayerEntered:Fire(player)
end
end
charactersExited = Functions.ExclusiveInTable(previouslyTouching, currentlyTouching)
for _, character in pairs(charactersExited) do
CharacterExited:Fire(character)
player = Players:GetPlayerFromCharacter(character)
if player then
PlayerExited:Fire(player)
end
end
previouslyTouching = currentlyTouching
task.wait()
end
end)
coroutine.resume(hitboxCoroutine)
return self
end
-- [Object Functions]
function Hitbox:GetTouchingPlayers() -- Get Players in Hitbox
local touchingPlayers = {}
local player
for _, part in pairs(workspace:GetPartsInPart(self.Part)) do
player = game.Players:GetPlayerFromCharacter(part.Parent)
if not table.find(touchingPlayers, player) then
table.insert(touchingPlayers, player)
end
end
return touchingPlayers
end
function Hitbox:GetTouchingCharacters() -- Get Characters in Hitbox
local touchingCharacters = {}
for _, part in pairs(workspace:GetPartsInPart(self.Part)) do
local character = part.Parent
if not table.find(touchingCharacters, character) and character:FindFirstChildOfClass("Humanoid") then
table.insert(touchingCharacters, character)
end
end
return touchingCharacters
end
function Hitbox:Destroy() -- Destroy a Hitbox Object
self.Active = false
self = nil
end
return Hitbox