If you don’t know anything about MetaTables and MetaMethods, I suggest you read up on articles about those:
Hey, this tutorial will teach you on how to create your own zone module!
Let’s start by creating a module script. It should look like this
local Module = {}
return Module
You can change the module name to anything you like!
Next, we need to set variables.
--// Variables
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
One of the most important things here is the __index metamethod.
module.__index = module
This will basically make it so when you index the module and it returns nil, it returns back to the module.
We also need a function to make this zone module happen!
function getPlayer(part: Model)
return Players:GetPlayerFromCharacter(part.Parent)
end
This function will basically return the player when the first parameter is a Character model.
We need to create a function within the module which will create the zone.
function module.new(Container: Part)
end
The container parameter is basically the whole base. Its the whole zone which we will use to detect Touches.
function module.new(Container: Part)
local self = setmetatable({}, ZoneModule)
return self
end
function module.new(Container: Part)
local self = setmetatable({}, ZoneModule)
self.Name = Container.Name
self.CFrame = Container.CFrame
end
We created properties within self (the table) which will help us creating Touched Events and stuff like that.
We also need BindableEvents to create events like Zone.Touched
self.PlayerEnteredEvent = Instance.new("BindableEvent")
self.PlayerLeftEvent = Instance.new("BindableEvent")
self.TouchedEvent = Instance.new("BindableEvent")
self.PlayerEntered = self.PlayerEnteredEvent.Event
self.Touched = self.TouchedEvent.Event
Lets create our touched event!
RunService.Stepped:Connect(function()
local PlayersInZone = {}
local PartsInZone = workspace:GetPartBoundsInBox(self.CFrame, self.Size)
end)
GetPartBoundsInBox will basically detect what parts are in a certain part, which will be really handy.
We also need a line of code to stop the function if there is nothing in the box.
if #PartsInZone == 0 then return end
Then, we need to loop through all the parts in the box
for _, part in pairs(PartsInZone) do
if part.Name ~= self.Name then -- Checks if the part in the box is not the container part.
self.TouchedEvent:Fire(part) -- Fires the bindable event when a part touches the zone.
end
end
Now, we need to make the player entered event work.
local PlayerInBox = getPlayer(part.Parent)
if PlayerInBox then
if PlayersInZone[PlayerInBox] then return end -- If theres already a player in the zone then stop the function
PlayersInZone[PlayerInBox] = PlayerInBox
self.PlayerEnteredEvent:Fire(PlayerInBox)
end
That’s basically it on creating the module! The full script should look like this:
local ZoneModule = {}
ZoneModule.__index = ZoneModule
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
function getPlayer(part: Model)
return Players:GetPlayerFromCharacter(part.Parent)
end
ZoneModule.new = function(Container: Part)
local self = setmetatable({}, ZoneModule)
self.Name = Container.Name
self.CFrame = Container.CFrame
self.PlayerEnteredEvent = Instance.new("BindableEvent")
self.TouchedEvent = Instance.new("BindableEvent")
self.PlayerEntered = self.PlayerEnteredEvent.Event
self.PlayerLeft = self.PlayerLeftEvent.Event
self.Touched = self.TouchedEvent.Event
local PlayersInZone = {}
RunService.Stepped:Connect(function()
local PartsInZone = workspace:GetPartBoundsInBox(self.CFrame, self.Size)
if #PartsInZone == 0 then return end
for _, part: Instance in (PartsInZone) do
if part.Name ~= self.Name then
self.TouchedEvent:Fire(part)
local PlayerInBox = getPlayer(part.Parent)
if PlayerInBox then
if PlayersInZone[PlayerInBox] then return end
PlayersInZone[PlayerInBox] = PlayerInBox
self.PlayerEnteredEvent:Fire(PlayerInBox)
end
end
end
end)
return self
end
This is my first tutorial ever. Tips would really help me learn, so if you have any please type them below.