Overview
RBLX Essentials is a collection of modular, production-ready Roblox game systems distributed as plug-and-play packs. Each pack installs in minutes via a dedicated Studio plugin, requires no manual scripting to set up, and integrates automatically with the other packs in the ecosystem.
The goal is to give Roblox developers a solid, tested foundation so they can focus on what makes their game unique instead of rebuilding common systems from scratch.
Pack Catalogue
| Pack | PackId | Version | Description |
|---|---|---|---|
| Ecosystem Core | EcosystemCore | 1.0.7 | Shared UI foundation required by all tag-based packs. Install this first. |
| Datastore & Purchase System | DatastorePurchaseSystem | 1.0.7 | Player data persistence, game pass validation, and developer product handling. |
| Easy Pet System | EasyPetSystem | 1.0.16 | Full egg hatching, pet collection, merging, and equip system with multiplier API. |
| Sound System | SoundSystem | 1.0.13 | Centralised client/server SFX playback with positional and global audio. |
| General UI Kit | GeneralUIKit | 1.0.12 | Tag-based UI framework (CollectionService + Attributes) for panels and buttons. |
| Easy Leaderstats & Leaderboards System | EasyLeaderstatsSystem | 1.0.4 | Tab-menu leaderstats and physical in-world global leaderboards, both plugin-managed. |
Dependency Matrix
Ecosystem Core is bundled in every pack. The table shows additional dependencies and synergies.
| Sound System | Datastore | UI Kit | Pet System | Leaderstats | |
|---|---|---|---|---|---|
| Sound System Free |
— | Pairs | Pairs | ||
| Datastore & Purchase Free |
— | Pairs | Pairs | Pairs | |
| General UI Kit $12.99 |
Bundled | Bundled | — | Pairs | |
| Easy Pet System $4.99 |
Bundled | Bundled | Pairs | — | |
| Easy Leaderstats $3.99 |
Bundled | — |
Architecture Philosophy
Modular. Each pack is a self-contained Rojo project. You install only what you need.
Plugin-managed. The RBLX Essentials Plugin handles deployment. It copies pack code from ServerStorage into the correct game services (StarterGui, ServerScriptService, ReplicatedStorage, etc.) with one click. No manual file placement.
Configuration over code. All user-facing settings live in ServerStorage under each pack's Settings folder. The plugin renders them as a form. You change values in the plugin; you do not touch scripts.
Shared infrastructure. Packs that depend on each other communicate through well-defined APIs (GUIBridge, DataStoreManager, PurchaseManager). There is no hidden coupling.
Getting Started
Requirements: Roblox Studio (any recent version). API Services must be enabled in your place if you use Datastore & Purchase System.
Step 1: Install the Plugin
Download the RBLX Essentials Plugin from Itch.io and drag the .rbxm file into Studio. It installs automatically to your Plugins folder. Restart Studio once.
The plugin appears as RBLX Essentials in the Plugins toolbar.
Step 2: Drag a Pack into Studio
- Download any pack
.rbxmfrom Itch.io. - Drag the file into your Studio Workspace (it lands there temporarily).
- Open the plugin (Plugins → RBLX Essentials).
The plugin will detect the pack and show both Ecosystem Core and the pack in its list.
Note: Ecosystem Core is bundled inside every pack, you do not download it separately. It will always appear in the plugin list when you drag in any pack.
Step 3: Install the Packs
Always install Ecosystem Core first, then the pack you dragged in.
- Click Ecosystem Core in the pack list and click Move & Install.
- Once done, select your pack and click Move & Install.
Repeat Step 2 and Step 3 for each additional pack. Follow this install order when combining packs:
- Ecosystem Core: always first (bundled, install before anything else).
- Datastore & Purchase System: no other dependencies.
- Sound System: no other dependencies.
- General UI Kit: requires Ecosystem Core (already installed). Sound System is optional.
- Easy Pet System: requires Datastore & Purchase System. Sound System is optional.
Step 4: Enable API Services
If you are using the Datastore & Purchase System, go to:
Game Settings → Security → Enable Studio Access to API Services
Without this, player data will not save in Studio playtests.
Step 5: Configure
Select any installed pack in the plugin to open its settings panel. Change values directly in the panel, no script editing required.
Typical things to configure:
- Easy Pet System: egg prices, drop rates, pet multipliers, gamepass IDs.
- Datastore & Purchase System: auto-save interval, DataStore name.
- Sound System: which Music Player template to use, enable/disable Music Player.
Step 6: Press Play
Hit Play in Studio. All packs initialise automatically. No bootstrap code, no wiring required.
Uninstalling a Pack
Select the pack in the plugin and click Uninstall Pack. The pack's deployed code is removed from all services. The pack template stays in ServerStorage so you can reinstall at any time.
Uninstalling Ecosystem Core does not clean up any packs that depend on it. Remove dependent packs manually first.
Plugin
The plugin is the package manager for the RBLX Essentials ecosystem. It handles discovery, deployment, configuration, and removal of packs, all within Studio without touching any project files manually.
How It Works
The plugin has three core systems. These run internally and are not visible in the UI, but understanding them helps if you want to know what happens under the hood.
Scanner reads ServerStorage.RBLXEssentials looking for _manifest folders. Each manifest identifies a pack (PackId, Version, DisplayName). This is how the plugin knows which packs are present in the project.
Verifier compares the pack's source in ServerStorage against the deployed code in the actual game services (StarterGui, ServerScriptService, ReplicatedStorage, etc.). This produces a status for each pack.
Installer copies pack code from ServerStorage into the target services on demand, and removes it on uninstall.
Pack Statuses
| Status | Meaning |
|---|---|
present | Pack is in ServerStorage but not yet deployed to game services. |
installed | Pack is fully deployed and matches the ServerStorage source. |
modified | Pack is deployed but scripts differ from the ServerStorage source (edited manually). |
workspace | Pack .rbxm was dropped into Workspace and needs to be moved to ServerStorage first. |
outdated | A newer version is available on Itch.io. Current version is in ServerStorage but not installed. |
available | Pack exists in the RBLX Essentials catalogue but has not been downloaded yet. |
Registry and Update Checks
On each refresh the plugin fetches a remote registry that lists all available packs and their latest versions. This powers two features:
- Catalogue listing: packs not yet downloaded appear in a separate "More from RBLX Essentials" section so you can discover them.
- Plugin update banner: if a newer version of the plugin itself is available, a banner appears at the top of the plugin UI.
The registry fetch is non-blocking: the plugin renders local packs immediately, then updates the list when the fetch completes.
Ecosystem Core Requirement
No pack can be installed unless Ecosystem Core is already deployed. The plugin enforces this by checking Verifier status for Ecosystem Core before allowing any install action. The install button shows "Install Ecosystem Core first" and is disabled until EC is deployed.
Settings Panel
Selecting an installed pack opens a settings panel on the right side of the plugin. The panel reads the pack's Settings folder from ServerStorage and renders each value as an editable field. Changes are applied directly to the ServerStorage instances and take effect on the next Play session.
Ecosystem Core
RequiredPackId: EcosystemCore · Version: 1.0.7 · Dependencies: None
What It Does
Ecosystem Core is the shared UI foundation for the RBLX Essentials ecosystem. It must be installed before any pack that uses the shared UI system.
It provides:
- A central GUI manager that discovers your panels, buttons, and decorative animations and wires them up automatically.
- GUIBridge: a cross-pack handler registry that lets each pack register its own button actions without knowing about the others.
- Panel-open animations, image preloading, tooltip hover effects, toggle buttons, and effect icon management, shared across all installed packs.
You don't need to know any of this to use RBLX Essentials packs. Everything runs automatically once installed. However, if you want to use Ecosystem Core's APIs in your own code, the full reference is below.
GUIBridge API
GUIBridge lives in ReplicatedStorage.RBLXEssentials.EcosystemCore.Shared. Require it from any LocalScript.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GUIBridge = require(ReplicatedStorage.RBLXEssentials.EcosystemCore.Shared.GUIBridge)
GUIBridge.registerHandlers(handlers)
Registers a table of action handlers. Call this once per pack during initialisation.
GUIBridge.registerHandlers({
OpenShop = function(button)
-- open the shop panel
end,
BuyItem = function(button)
-- handle purchase
end,
})
If two packs register the same action name, the last registration wins.
GUIBridge.dispatch(action, button)
Calls the registered handler for action. The GUIManager calls this automatically when a button with a custom Action is clicked — you do not need to call it manually. The built-in actions TogglePanel and ClosePanel are handled internally and never reach dispatch.
GUIBridge.getPanel(panelId)
Returns the UI_Panel-tagged GuiObject with the given PanelId attribute, searching the local PlayerGui. Returns nil if not found.
local shopPanel = GUIBridge.getPanel("Shop")
Only call this inside a running LocalScript after the GUI has loaded.
How Elements Are Discovered
Ecosystem Core uses two mechanisms: CollectionService tags for panels and toggle buttons, and attribute-driven discovery for regular buttons and decorative animations. Only UI_Panel and UI_Toggle are real tags — buttons and animated elements need no tag at all.
Tags
| Tag | Applied To | Attributes | Behaviour |
|---|---|---|---|
UI_Panel |
A panel (direct child of the Menus folder) |
PanelId (string), Exclusive (bool), Animation (string) |
Makes the panel findable via GUIBridge.getPanel. |
UI_Toggle |
A GuiButton |
Action (string) |
Auto-wired on/off toggle button. See Toggle Buttons below. |
PanelId vs panel Name: PanelId is used only by GUIBridge.getPanel(panelId). Panel toggling (TargetPanel, TogglePanel, ClosePanel) keys on the panel instance's Name, not its PanelId. Keep PanelId equal to the panel's Name so both lookups agree.
Exclusive panels: exclusive is the default — a panel with no Exclusive attribute closes other open panels when it opens. Set Exclusive = false to keep other panels open alongside this one (non-exclusive panels are also left open when an exclusive panel opens).
Animation: selects the panel-open animation by name, default "Bounce". See Panel Animations below.
Buttons (attribute-driven)
Any GuiButton descendant of the GUI with a non-empty Action attribute is wired automatically — no tag required.
| Attribute | Type | Behaviour |
|---|---|---|
Action | string (required) | The action to run on click. TogglePanel and ClosePanel are built in; anything else dispatches through GUIBridge. |
TargetPanel | string | Panel Name the built-in actions operate on. |
ShowTooltip | bool | Shows the shared tooltip on hover, following the mouse. |
TooltipText | string | Tooltip label text. Defaults to the button's Name. |
BuySound | bool | Plays the purchase sound instead of the standard press sound on click. |
Buttons also get hover SFX and an icon scale-up effect for free (a child named Icon is tweened on hover).
Animated Decorations (attribute-driven)
Any non-panel GuiObject with an Animation attribute becomes a decorative animated element — no tag required.
Animation value | Optional Attributes | Behaviour |
|---|---|---|
Rotate | Speed (number) | Continuous full rotation. Speed is the tween duration in seconds for one full rotation (default 15) — larger values spin slower. |
HoverBob | — | Bobs up slightly on mouse enter, settles back on leave. Speed is ignored. |
Built-in Button Actions
These actions are handled by the GUIManager itself and never reach GUIBridge:
| Action | Effect |
|---|---|
TogglePanel | Toggles the panel whose Name matches TargetPanel. Opening it plays the panel's open animation, resets its ScrollingFrames to the top, and closes other exclusive panels. |
ClosePanel | Closes the panel whose Name matches TargetPanel. If TargetPanel is empty or absent, the button closes its nearest ancestor panel instead — handy for a close button placed inside the panel it closes, with no configuration. |
Toggle Buttons (UI_Toggle)
Tag any GuiButton with UI_Toggle and Ecosystem Core wires it as a stateful on/off switch:
- Starts in the on state.
- Each click flips the state and dispatches the button's
Actionattribute through GUIBridge, so your handler receives every change. - The button's background turns green (
Color3.fromRGB(85, 255, 0)) when on and red (Color3.fromRGB(255, 50, 50)) when off. - A child
TextLabelnamedStatus, if present, is updated to"ON"/"OFF". - Buttons tagged at runtime are wired automatically — spawn toggle buttons whenever you like.
GUIBridge.registerHandlers({
ToggleMusic = function(button)
-- read the visual state, or track your own
MusicController:SetEnabled(not MusicController.Enabled)
end,
})
Panel Animations
Panel-open animations are ModuleScripts under the GUIManager's PanelAnimations folder. Each module returns a single function:
-- PanelAnimations/SlideIn.lua
return function(menu: GuiObject)
local origPos = menu.Position
menu.Position = origPos + UDim2.fromScale(0.1, 0)
menu:TweenPosition(origPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quint, 0.3, true)
end
A panel's Animation attribute selects the animation by module name; the default is "Bounce", which ships with the pack. Bounce drops the panel in from slightly above with a subtle rotation settle — it requires the panel to be a CanvasGroup and is a no-op otherwise.
This is an extension point: other RBLX Essentials packs can contribute their own animation modules, and the loader aggregates modules from sibling packs automatically. Drop in a new ModuleScript and reference its name from any panel's Animation attribute.
Notes
- Image preloading is batched (2 images per frame) to avoid frame hitches on startup.
- Sound playback degrades gracefully if Sound System is not installed.
- Opening a panel resets its ScrollingFrames'
CanvasPositionto the top; scrolling itself is native Roblox behaviour.
Datastore & Purchase System
PackId: DatastorePurchaseSystem · Version: 1.0.7 · Dependencies: None
What It Does
The Datastore & Purchase System is the data and monetisation backbone of RBLX Essentials. It handles:
- Loading and saving player data automatically on join/leave.
- An in-memory cache so all reads mid-session are instant.
- Game pass ownership checks with caching.
- Developer product purchase callbacks with receipt history to prevent duplicate grants.
- Automatic retry with exponential backoff to handle Roblox DataStore throttling.
All other RBLX Essentials packs that need to persist data (e.g. Easy Pet System) read and write through this system. There is only one DataStore per game, no duplicate stores or conflicting keys.
This pack can also be used on its own. You don't need any other RBLX Essentials pack installed to use it in your game.
Plugin Configuration
All settings are managed directly from the plugin, no script editing needed.
Datastore Settings
- AutoSaveInterval: how often (in seconds) player data is saved automatically. Default is 90.
- DataStoreVersion: the DataStore key version used in production. Increment this to reset all player data (e.g. for a game wipe).
- StudioDataStoreVersion: same as above but only applies in Studio, so you can wipe test data without affecting live players.
- Wipe Studio Data: clears all locally stored Studio test data immediately.
Default Data
Defines the default data structure for new players. Data is organised into groups (e.g. Stats, Pets, Meta), each containing variables with a default value. You can add, remove, and rename groups and variables freely. This structure is what every new player starts with on their first join.
Add a new Variable
Clicking + New Variable shows a row where you write the variable name and select its type:
- Num: a number (e.g. Cash, XP).
- Str: a string of text.
- Bool: a true/false value.
- List: an array (e.g. for storing a list of owned items).
Add a new Group
Clicking + New Group shows a field to enter the group name:
Purchase Settings
- FreeMode: when ON, all game pass checks return
truefor all players. Useful for testing without real purchases. - Purchases: the list of game passes and developer products registered in the system. Each entry has a name, a type (
gamepassorproduct), and the Roblox asset ID. Add your passes here so the system can handle ownership checks and purchase callbacks.
Before testing: create your Game Passes in the Roblox Creator Dashboard for your experience, then paste each Game Pass ID into the Id field of the corresponding entry in the plugin. Without a real ID, ownership checks won't work.
Uninstalling
Removes the pack's deployed folders from all service locations. The pack template stays in ServerStorage so you can reinstall at any time.
That's everything from the plugin.
If you're not planning to modify the pack's code or call its APIs from your own scripts, you can stop here. The sections below are for developers who want to integrate the system directly into their own code.
DataStoreManager API
Require the provider from any Script or ModuleScript in ServerScriptService. It returns the manager instance directly.
local Manager = require(
ServerScriptService.RBLXEssentials.DatastorePurchaseSystem.DataStoreSystem.ManagerProvider
)
Manager:Get(player)
Returns the player's complete data table. The first call loads from DataStore and caches the result; subsequent calls return the cache instantly. Concurrent first calls are deduplicated — every caller receives the same table.
local data = Manager:Get(player)
print(data.Stats.Cash)
Manager:Update(player, mutator)
Applies a mutation function to the player's data and pushes the change to the client replica. The mutator receives the data table directly. Changes persist automatically on the next auto-save (every AutoSaveInterval seconds) and when the player leaves — mutate the table only through Update so the client replica stays in sync.
Manager:Update(player, function(data)
data.Stats.Cash += 100
end)
Manager:Save(player)
Queues an early save for the player, ahead of the auto-save schedule. Use after important changes (big purchases, milestone progress). Returns immediately; the write happens in the background respecting the DataStore budget.
Client-side data access
Every player's data is mirrored under their Player instance as Folders and Value objects, updated live on every Update — no remotes needed to display stats. Arrays replicate as children named [1], [2], … The replica is read-only by convention.
-- LocalScript
local player = game.Players.LocalPlayer
local playerData = player:WaitForChild("PlayerData")
playerData:WaitForChild("ready") -- present once the first replication completed
local cash = playerData.Stats.Cash
cashLabel.Text = tostring(cash.Value)
cash:GetPropertyChangedSignal("Value"):Connect(function()
cashLabel.Text = tostring(cash.Value)
end)
PurchaseManager API
Studio note: By default, Roblox Studio treats the local player as owning all game passes. Gamepass checks will always return true in a regular Play session. To test real purchase behaviour, use the Server & Clients mode in Studio, which simulates a live server environment.
local PurchaseManager = require(
ServerScriptService.RBLXEssentials.DatastorePurchaseSystem.PurchaseManager.PurchaseManager
)
PurchaseManager.HasPass(player, passId)
Returns true if the player owns the game pass. Checks the in-memory cache first, then the player's saved data, then MarketplaceService (persisting a confirmed ownership back to the DataStore). Returns true for everyone while FreeMode is enabled. The cache invalidates automatically when a player buys a pass mid-session.
if PurchaseManager.HasPass(player, 123456789) then
-- grant perk
end
PurchaseManager.registerHandler(productId, callback)
Registers a handler for a developer product. The callback receives (player, receiptInfo) and must return true to confirm the purchase. Returning false or erroring will cause Roblox to retry the receipt.
PurchaseManager.registerHandler(987654321, function(player, receipt)
Manager:Update(player, function(data)
data.Stats.Cash += 1000
end)
return true
end)
PurchaseManager.InvalidatePass(player, passId)
Clears the cached ownership result for a pass, forcing a fresh check on the next HasPass call. This is called automatically when a player purchases a pass mid-session, you only need to call it manually if you have an external reason to force a re-check.
PurchaseManager.GrantProduct(player, productId)
Directly invokes a registered product handler without a real purchase. Only works while FreeMode is enabled — useful for testing reward flows in Studio. Note the handler receives nil as receiptInfo in this path.
Default Player Data Schema
{
Meta = {
SchemaVersion = 1
},
Stats = {
Cash = 0
},
Pets = {
Equipped = {},
Owned = {}
},
Purchases = {
Gamepasses = {}
}
}
Missing keys return their default values automatically. Existing players receive new defaults on their next load, no migration needed. New keys and entirely new top-level groups can be added either via the Settings > Default Data folder in the plugin, or directly in DefaultData.lua. Both approaches are equivalent: on load, the system merges the player's saved data with the current defaults and fills in anything missing.
Configuration
Settings live in ServerStorage.RBLXEssentials.DatastorePurchaseSystem.Settings and are editable via the plugin.
| Setting | Ships as | Description |
|---|---|---|
DataStoreVersion | "v1" | Key suffix for the production DataStore (PlayerData_v1). Change it to start every player on a fresh data slate. |
StudioDataStoreVersion | "v4" | Key suffix used while testing in Studio, kept separate so tests never touch live player data. |
AutoSaveInterval | 90 | Seconds between automatic periodic saves per player (smoothed and jittered to respect DataStore budgets). |
FreeMode | true | Bypasses all pass checks and lets GrantProduct run handlers for free. Ships enabled for development — turn it OFF before going live. |
Wipe Studio Data | action | Plugin button that deletes all keys in the current Studio DataStore version — a clean slate for testing. Never touches live data. |
Easy Pet System
PackId: EasyPetSystem · Version: 1.0.16 · Dependencies: Datastore & Purchase Sound System (optional)
What It Does
Easy Pet System is a complete, production-ready pet system for Roblox. Players hatch pets from eggs, collect them across rarity tiers, merge duplicates into rarer versions, equip pets that follow them around the map, and earn multiplier bonuses.
- Weighted rarity rolls for egg hatching (single and triple hatch).
- Auto-hatch gamepass support.
- Triple-hatch gamepass support.
- Extra Pet Space gamepass support.
- Three pet movement modes — Ground, Float (orbit), and Follow — switchable at runtime.
- Merge 3 pets of the same type into the next rarity tier.
- Merge All: auto-merges all eligible sets in one call.
- Equip Best: automatically equips the highest-multiplier combination.
- Multiplier API: sum or product of all equipped pet multipliers, accessible from any server script.
- 28 included pet models across 5 rarities (fully replaceable).
- BillboardGui egg hatching animations.
Plugin Configuration
Required: this pack uses Roblox DataStore. Go to Game Settings → Security → Enable Studio Access to API Services before testing, otherwise player data will not save.
All settings are managed directly from the plugin, no script editing needed.
Purchase Settings
Lists the game passes used by the pack. Each entry has a warning to replace the default ID with your own from the Roblox Creator Dashboard.
- ExtraPetSpace: allows players to equip a 4th pet.
- AutoHatch: allows players to auto-hatch eggs continuously.
- TripleHatch: allows players to hatch 3 eggs at once.
Before testing: create these Game Passes in the Roblox Creator Dashboard for your experience and paste each ID into the corresponding field. Without real IDs, ownership checks won't work.
Pet Data
- MaxOwned: maximum number of pets a player can have in their inventory.
- MaxEquipped: maximum number of pets a player can have equipped at once (increased to 4 with the ExtraPetSpace pass).
- MergeCount: number of pets of the same type required to perform a merge.
- ProximityDistance: stud distance within which pets stay near the player.
- FollowMode: how pets move relative to the player. Options:
Ground,Orbit,Follow.Orbitis labelled "Float" in the in-game Settings panel.
Rarities
Rarities are defined in ReplicatedStorage > RBLXEssentials > EasyPetSystem > PetSystem > PetData > Rarities. You can add, remove, and rename rarities freely. Pets reference rarities by name.
| Value | Type | Controls |
|---|---|---|
order | number | Tier rank used for pet sorting in the Pets menu and for determining the merge target (next rarity up). Lower = weaker. |
frameColor | Color3 | Border/stroke colour of each pet slot in the egg billboard GUI, and the probability percentage text colour. |
textColor | Color3 | Pet name label text colour in the egg billboard GUI. |
frameColor2 | Color3 | Read by PetConfig but not currently applied anywhere. Reserved for future use. |
labelColor | Color3 | Read by PetConfig but not currently applied anywhere. Reserved for future use. |
The colours of pet cards in the Pets menu and in the hatch toast are not driven by these values. They are baked into each [Rarity]PetTemplate frame (gradient and UIStroke) and read from there at runtime.
Pet Card Templates
The actual pet cards rendered inside the Pets menu use rarity-specific UI templates located in:
MenusGUI > Menus > Pets > Container > PetContainer > Container
Each template is a Frame named [Rarity]PetTemplate (e.g. CommonPetTemplate, EpicPetTemplate) and tagged in CollectionService with the same name. When a pet card is rendered, the system resolves the correct template by tag:
CollectionService:GetTagged(petDef.rarity .. "PetTemplate")
The matching template is cloned and populated with the pet's data. Colours, gradients, and border styles are baked directly into each template and are not applied dynamically at runtime.
To add a new rarity, create a new Frame in the container, name it [NewRarity]PetTemplate, and apply the CollectionService tag [NewRarity]PetTemplate to it.
Pets
The full list of pets in the game. Each pet has a preview image (the 3D model), a name, a rarity, and a multiplier value. You can add new pets, delete existing ones, or change any of their properties here.
Eggs
Defines all eggs available in the game. Each egg has a name, a price, a currency (Cash or Robux), and a drop percentage table listing which pets can be hatched from it and at what probability. The total must add up to 100%.
At the bottom you can create a new Cash Egg or a Robux Egg.
Robux Eggs
Robux eggs use robuxPrice (the display price in Robux) and a productId (the Developer Product ID from the Roblox Creator Dashboard) instead of a cash price.
Uninstalling
Removes the pack's deployed folders from all service locations. The pack template stays in ServerStorage so you can reinstall at any time.
That's everything from the plugin.
If you're not planning to modify the pack's code or call its APIs from your own scripts, you can stop here. The sections below are for developers who want to integrate the system directly into their own code.
PetService API
Require from any Script or ModuleScript in ServerScriptService.
local PetService = require(ServerScriptService.RBLXEssentials.EasyPetSystem.PetSystem.PetService)
PetService.GetTotalMultiplier(player, multiply?)
Returns the combined multiplier of all equipped pets.
-- Sum all equipped multipliers (e.g. 1 + 1.5 + 2 = 4.5)
local total = PetService.GetTotalMultiplier(player)
-- Multiply all equipped multipliers (e.g. 1 * 1.5 * 2 = 3.0)
local product = PetService.GetTotalMultiplier(player, true)
-- Apply to a reward
local reward = baseCash * PetService.GetTotalMultiplier(player)
PetService.HatchEgg(player, eggId, count, isAuto?)
Hatches one or three pets from the specified egg. Returns a result table.
local result = PetService.HatchEgg(player, "Tier1Egg", 1)
if result.ok then
for _, pet in result.pets do
print(pet.id, pet.rarity, pet.multiplier)
end
end
Parameters:
eggId(string): must match a key in the Eggs configuration.count(number):1for single hatch,3for triple (requires TripleHatch pass).isAuto(bool, optional):truefor auto-hatch (requires AutoHatch pass).
Failure reasons: "invalid_egg", "insufficient_funds", "inventory_full", "need_triple_pass", "need_auto_pass", "cooldown".
Each pet in result.pets has: uid, id, rarity, multiplier, createdAt.
PetService.EquipPet(player, uid)
Equips a pet by its unique ID. Players can have up to 3 pets equipped (4 with the ExtraPetSpace pass).
PetService.UnequipPet(player, uid)
Unequips a pet by its unique ID.
PetService.DeletePet(player, uid)
Deletes a pet from the player's inventory. The pet must be unequipped first.
PetService.MergePets(player, petId)
Merges 3 pets of the same type into one pet of the next rarity tier. Non-equipped pets are consumed first; if there aren't enough, the remaining merge slots are filled from equipped pets, which are unequipped before being consumed.
local result = PetService.MergePets(player, "Cat")
if result.ok then
print("Merged into:", result.pet.rarity)
end
Failure reasons: "no_next_tier", "not_enough", "invalid_pet".
PetService.MergeAll(player)
Merges all eligible pet sets in a single call.
local result = PetService.MergeAll(player)
print("Merges performed:", result.mergeCount)
PetService.EquipBest(player)
Unequips all current pets and re-equips the combination with the highest total multiplier, up to the equip limit.
Configuration
Pets, eggs, rarities, and core limits are all data-driven — edit them in the Explorer or through the plugin's settings panel without touching code. Pet movement behaviour (radius, speed, bobbing) is tuned in one editable Lua module, PetVisualsConfig (see below).
Key Settings
| Setting | Default | Description |
|---|---|---|
MaxOwned | 50 | Maximum pets a player can hold in their inventory. |
MaxEquipped | 3 | Base number of pets a player can equip simultaneously. |
MergeCount | 3 | Number of pets required to perform a merge. |
FollowMode | "Ground" | How pets move relative to the player. Options: "Ground", "Orbit", "Follow". Orbit is labelled "Float" in the in-game Settings panel. |
ProximityDistance | 7 | Stud distance within which pets stay near the player. |
Switching Follow Mode at Runtime
The active movement mode is controlled by a PetFollowMode attribute on the local player. Set it from any LocalScript — the Settings panel does exactly this:
local Players = game:GetService("Players")
Players.LocalPlayer:SetAttribute("PetFollowMode", "Orbit") -- "Ground", "Orbit", or "Follow"
Pets react immediately; no rejoin or respawn required. If the attribute is unset, the mode falls back to PetVisualsConfig.DefaultMode.
Tuning Pet Movement: PetVisualsConfig
ReplicatedStorage > RBLXEssentials > EasyPetSystem > PetSystem > PetVisualsConfig is an editable ModuleScript that defines every movement mode and its parameters:
return {
DefaultMode = "Ground",
Modes = {
Orbit = {
label = "Float", -- name shown in the Settings panel
Radius = 4, -- studs from character center
Speed = 45, -- degrees per second
FloatHeight = 2.5, -- studs above HumanoidRootPart
BobAmount = 0.25, -- vertical bob amplitude (studs)
BobSpeed = 1.2, -- bob frequency (Hz)
LerpAlpha = 0.15,
},
Ground = {
label = "Ground",
Radius = 4,
Speed = 35,
FloatHeight = -2, -- floor level relative to HumanoidRootPart
BobAmount = 0,
BobSpeed = 0,
LerpAlpha = 0.15,
},
Follow = {
label = "Follow",
Spacing = 2.5, -- studs between each pet in the trail
FloatHeight = -2,
LerpAlpha = 0.1,
},
},
}
Adjust radius, orbit speed, float height, bobbing, or trail spacing here to change how equipped pets move.
Reading Configuration in Code: PetConfig
ReplicatedStorage > RBLXEssentials > EasyPetSystem > PetSystem > PetConfig loads the full PetData tree into a plain Lua table, usable from both client and server:
local PetConfig = require(ReplicatedStorage.RBLXEssentials.EasyPetSystem.PetSystem.PetConfig)
print(PetConfig.MaxOwned, PetConfig.MaxEquipped, PetConfig.MergeCount)
print(PetConfig.ProximityDistance, PetConfig.FollowMode)
local catDef = PetConfig.Pets["Cat"] -- { name, rarity, multiplier }
local eggDef = PetConfig.Eggs["Tier1Egg"] -- { name, price, currency, pets, robuxPrice?, productId? }
local rarity = PetConfig.Rarities["Epic"] -- { order, frameColor, frameColor2, textColor, labelColor }
PetConfig.getNextRarityPets(petId) returns the merge candidates for a pet — the { id, percent } entries from the same egg at the next rarity tier — or nil if the pet is already the highest rarity in its egg:
local candidates = PetConfig.getNextRarityPets("Cat")
if candidates then
for _, entry in candidates do
print(entry.id, entry.percent)
end
end
Gamepasses
Configure these pass IDs in the plugin settings to enable the corresponding features:
| Gamepass | Effect |
|---|---|
TripleHatch | Allows hatching 3 eggs at once. |
AutoHatch | Allows continuous auto-hatching. |
ExtraPetSpace | Increases the equip limit from 3 to 4. |
Client Integration: Remotes
On startup, the Bootstrap server script publishes the client-facing surface under ReplicatedStorage > PetSystem:
PetSystem > Remotes
| Remote | Type | Invoked with |
|---|---|---|
BuyAndHatchEgg | RemoteFunction | { eggId = "Tier1Egg", count = 1, isAuto = false } |
GrantFreeProduct | RemoteFunction | — |
EquipPet | RemoteFunction | pet uid |
UnequipPet | RemoteFunction | pet uid |
DeletePet | RemoteFunction | pet uid |
MergePets | RemoteFunction | petId |
EquipBest | RemoteFunction | — |
MergeAll | RemoteFunction | — |
PremiumHatchResult | RemoteEvent | fired server → client with Robux hatch results |
PetSystem > PassConfig — a folder the built-in UI reads for pass gating: NumberValues TripleHatch, AutoHatch, ExtraPetSpace (holding the pass IDs) and a BoolValue FreeMode (when true, all pass checks are bypassed).
Use these remotes to trigger pet actions from your own UI:
local Remotes = ReplicatedStorage:WaitForChild("PetSystem"):WaitForChild("Remotes")
local result = Remotes.BuyAndHatchEgg:InvokeServer({
eggId = "Tier1Egg",
count = 1,
isAuto = false,
})
if result.ok then
print("Hatched:", result.pets[1].id)
end
Adding Egg Models to the Map
Egg models in Workspace are discovered by tag, so you can place as many as you like. Each egg Model must:
- Be tagged
Eggin CollectionService. - Have an
EggIdstring attribute matching a key in the Eggs configuration (e.g."Tier2Egg"). - Contain a part named
Guiholding aBillboardGuitaggedEggBoard— this is the hatch interface players interact with.
The simplest workflow: duplicate one of the included egg models, change its EggId attribute, and swap the mesh. The billboard, proximity detection, and hatch buttons wire themselves up automatically.
Hatch Toast
The hatch-reveal toast (the full-screen pet reveal after hatching) is exposed as a client module at ReplicatedStorage > RBLXEssentials > EasyPetSystem > PetSystem > HatchToast, so you can trigger it from your own flows:
local HatchToast = require(ReplicatedStorage.RBLXEssentials.EasyPetSystem.PetSystem.HatchToast)
if not HatchToast.IsBusy() then
HatchToast.ShowSingle(petData) -- one pet reveal
-- or
HatchToast.ShowTriple(pets) -- three-pet reveal (triple hatch)
end
HatchToast.IsBusy()— returnstruewhile a reveal is currently playing.HatchToast.ShowSingle(petData)— shows the reveal for one pet (a pet table withid,rarity, etc.).HatchToast.ShowTriple(pets)— shows the three-slot reveal for an array of pets.
Included Pets
28 pets across 5 rarities sourced from a Roblox asset pack. All pet models are fully replaceable, you can add, remove, or swap them at any time without code changes.
| Rarity | Multiplier Range |
|---|---|
| Common | x1 to x500 |
| Uncommon | x2 to x750 |
| Rare | x4 to x80,000 |
| Epic | x25 to x200,000 |
| Legendary | x400 to x1,500,000 |
Sound System
PackId: SoundSystem · Version: 1.0.13 · Dependencies: None for the audio core; Ecosystem Core required for the in-game settings-menu controls
What It Does
Sound System is a centralised audio system for Roblox with two halves:
- SFX: clean client and server APIs for playing sound effects, from simple UI sounds to positional 3D audio at a world location.
- Music player: a client-side music system that cycles through your track list, with a tag-based UI (song name, duration, mute, next) that you can drop into any GUI.
Both halves route through Roblox SoundGroups, so SFX and music volume are controlled independently — players can mute sound effects without touching the music, and vice versa.
Other RBLX Essentials packs (Easy Pet System, General UI Kit, Ecosystem Core) use Sound System for their audio feedback. It degrades gracefully if not installed — packs check for its presence before calling it.
Plugin Configuration
All settings are managed directly from the plugin, no script editing needed.
Sound Settings
- SFXEnabled: global SFX kill switch. Default:
true. When OFF, allPlay,PlayOverlap, andPlayAtcalls are silently ignored.
Music Player
- Template: which Music Player UI template to use. The templates are located in
ServerStorage > RBLXEssentials > SoundSystem > Templates. - MusicPlayerEnabled: gates the music subsystem. Default:
true. When OFF, the music player GUI is hidden and no music plays.
There are 6 built-in templates to choose from (MusicPlayer_Template_1 through MusicPlayer_Template_6). You can also modify any of them freely in Studio to match your game's visual style.
Uninstalling
Removes the pack's deployed folders from all service locations. The pack template stays in ServerStorage so you can reinstall at any time.
That's everything from the plugin.
If you're not planning to modify the pack's code or call its APIs from your own scripts, you can stop here. The sections below are for developers who want to integrate the system directly into their own code.
Sound Storage
Sounds live as Sound instances under two SoundGroup folders:
SoundService > RBLXEssentials > SoundSystem > SFX -- sound effects
SoundService > RBLXEssentials > SoundSystem > Music -- music tracks
Sounds are looked up by name. Add a Sound to the right folder in Studio and it's immediately available — the Bootstrap script auto-assigns each sound's SoundGroup, including sounds added at runtime.
SFX API
One module, one require path. SFXSystem lives in ReplicatedStorage and works from both the server and the client — it branches internally on RunService:IsServer(), so the same require line works in a Script or a LocalScript:
local SFX = require(game:GetService("ReplicatedStorage").RBLXEssentials.SoundSystem.SFXSystem)
Client methods
SFX:Play(name)
Plays a sound by name. If the sound is already playing, it restarts from the beginning.
SFX:Play("ButtonClick")
SFX:PlayOverlap(name)
Clones the sound and plays the clone. Multiple instances can overlap simultaneously. Each clone destroys itself when playback ends.
SFX:PlayOverlap("Coin")
Use PlayOverlap for sounds that can trigger rapidly (e.g. collecting coins, rapid button presses).
Server methods
SFX:PlayAt(name, position, range?)
Plays a sound for all clients at a world position.
- With a
range— 3D positional audio: an invisible hostPartis created at the position, the sound rolls off with distance (LinearSquare), and is audible up torangestuds. The part is destroyed when playback ends. - Without a range — global playback: the sound plays directly in the
SFXSoundGroup for every client, with no distance falloff. Because it stays in the group, it still respects the player's SFX volume and mute settings.
-- Global sound (no rolloff, plays through the SFX group)
SFX:PlayAt("Explosion", workspace.Bomb.Position)
-- 3D positional sound (audible within 40 studs)
SFX:PlayAt("Explosion", workspace.Bomb.Position, 40)
SFX:PlayAtForPlayer(player, name, position, range?)
Same as PlayAt but only plays for one specific player.
SFX:PlayAtForPlayer(player, "LevelUp", player.Character.HumanoidRootPart.Position)
Music Player
Drop your tracks into SoundService > RBLXEssentials > SoundSystem > Music and the client-side MusicSystem handles the rest: it builds the playlist, starts on a random track, advances automatically when a track ends, and keeps the list in sync if tracks are added or removed at runtime.
UI integration
The music player UI is tag-based. Tag any Frame with the CollectionService tag MusicPlayerFrame and give it this structure:
Frame (tagged MusicPlayerFrame)
└── Container
├── SongName (TextLabel)
├── Duration (TextLabel)
└── Buttons
├── Mute (ImageButton with an "Icon" child)
└── Next (ImageButton / TextButton)
MusicSystem wires everything up automatically:
- SongName shows the current track's name.
- Duration shows elapsed / total time (
1:23 - 3:05), updated live. - Mute toggles music mute (the icon swaps between playing and muted states).
- Next skips to the next track.
You can tag multiple frames — for example one in the HUD and one in a settings panel. All tagged frames share a single playback state, so muting from one updates every other frame instantly. Frames added or removed at runtime are picked up automatically.
Settings
Both settings are BoolValues under ServerStorage > RBLXEssentials > SoundSystem > Settings and are editable from the RBLX Essentials plugin. The Bootstrap script publishes them to ReplicatedStorage for the clients and keeps them in sync if changed at runtime.
| Setting | Default | Effect |
|---|---|---|
SFXEnabled | true | Global SFX kill switch — when false, all Play, PlayOverlap, and PlayAt calls are silently ignored. |
MusicPlayerEnabled | true | Gates the music subsystem — when false, the music player GUI is hidden and no music plays. |
Settings-Menu Integration (Ecosystem Core)
When Ecosystem Core is installed, Sound System registers a set of action handlers through EC's GUIBridge. Bind any of these to a button by setting its Action attribute — no code required:
| Action | Effect |
|---|---|
ToggleMusicMute | Mutes/unmutes music (restores the previous volume on unmute) |
ToggleSFXMute | Mutes/unmutes sound effects |
MusicVolumeUp / MusicVolumeDown | Steps music volume up/down |
SFXVolumeUp / SFXVolumeDown | Steps SFX volume up/down |
Volume moves along a 9-step ladder from 0.04 to 1.0, so each press is a perceptible change rather than a linear crawl. The handlers also drive optional UI feedback: mute buttons show an ON/OFF status, and a frame with a VolumeGroup attribute ("Music" or "SFX") containing Volume1–Volume9 segments renders as a live volume bar.
Everything stays in sync across surfaces — muting from the settings menu updates the music player's mute icon, and vice versa, because both operate on the same SoundGroups.
This integration is the only part of the pack that requires Ecosystem Core. The SFX and music APIs above are fully standalone.
Notes
- Positional sounds use
RollOffMode.LinearSquareand retain theirSoundGroup, so volume/mute settings still apply. - The invisible host
Partis created only for ranged playback and is destroyed when the sound ends; global playback clones the sound directly into theSFXgroup. - The
SFXEnabledandMusicPlayerEnabledvalues are published toReplicatedStorage > RBLXEssentials > SoundSystem > Configby the Bootstrap script.
General UI Kit
PackId: GeneralUIKit · Version: 1.0.12 · Dependencies: Ecosystem Core Sound System
What It Does
General UI Kit is a tag-based UI framework for Roblox. UI behaviour is declared through CollectionService tags and Instance Attributes, with no hardcoded paths or script modifications needed to add new panels or buttons.
It provides:
- Panel management (open/close, exclusive mode, animated transitions).
- Universal button sounds and tooltip hover effects.
- Decorative UI animations (rotation, hover bob).
- Effect icon system with tooltip descriptions.
- Live data binding — labels that automatically display and update player data.
- TextBox typing sounds.
- Dispatch integration with Ecosystem Core's GUIBridge for cross-pack button handling.
How It Works
The GUIManager (a LocalScript) discovers all tagged elements in PlayerGui at runtime. Tags declare what an element is; Attributes declare how it behaves. You tag a Frame as UI_Panel and set PanelId = "Shop", and GUIManager handles the rest.
Button actions are dispatched through GUIBridge.dispatch(). To handle an action in your own code, call GUIBridge.registerHandlers() with a table of action functions.
Plugin Configuration
All panel and button configuration is managed directly from the plugin. No script editing or manual attribute assignment needed.
Panels and Buttons
The Navigation Manager lets you configure every panel and its associated button from a single visual panel in Studio. Each panel row shows a live thumbnail preview alongside its settings.
- Exclusive: when enabled, opening this panel automatically closes all other open panels.
- Animation: cycle through available open/close animations (
Bounce,SpinReveal, or none). - Button assignment: pick which button in your UI toggles this panel from a dropdown. The plugin sets
TargetPanelon the selected button automatically. - Add New Panel & Button: inserts a pre-configured panel and its toggle button into the scene in one click.
That's everything from the plugin.
If you're not planning to modify the pack's code or call its APIs from your own scripts, you can stop here. The sections below are for developers who want to integrate the system directly into their own code.
Tag Reference
UI_Panel
A toggleable menu panel (Frame or ScreenGui).
| Attribute | Type | Required | Description |
|---|---|---|---|
PanelId | string | Yes | Unique identifier for this panel. |
Exclusive | bool | No | Default: true. When an exclusive panel opens, it closes every other open panel that is also exclusive. Set to false to let the panel stay open alongside others — non-exclusive panels are never auto-closed. |
Animation | string | No | Panel open animation. Default: "Bounce". See below for available animations. |
Panel animations. The PanelAnimations loader aggregates animation modules from every installed RBLX Essentials pack, so the available set grows with your installed packs:
"SpinReveal"— ships with General UI Kit."Bounce"(the default) — contributed by Ecosystem Core. Since Ecosystem Core is a required dependency, Bounce is always available.
Any pack (including your own code) can contribute more animations by placing a ModuleScript that returns function(menu: GuiObject) inside its MenusGUI/Scripts/PanelAnimations/ folder — the loader picks it up automatically, and the module name becomes the Animation attribute value.
UI_Button
A clickable button (TextButton or ImageButton) that dispatches an action.
| Attribute | Type | Required | Description |
|---|---|---|---|
Action | string | Yes | Action name. Built-in actions are handled by GUIManager; anything else is dispatched to GUIBridge on click. |
TargetPanel | string | No | The PanelId to act on. Only read when Action is TogglePanel or ClosePanel — it has no effect with other actions. |
ShowTooltip | bool | No | If true, shows the shared Button tooltip on hover (see UI_Tooltip). |
TooltipText | string | No | Text shown in the Button tooltip. Defaults to the button's Name. |
BuySound | bool | No | If true, plays the purchase sound instead of the standard click sound. |
Linking a button to a panel:
To open or close a panel from a button, set Action = "TogglePanel" and TargetPanel = "<PanelId>" on the button. No handler registration is required — GUIManager handles it automatically.
Example: a button that toggles the Shop panel.
- Panel frame: tag
UI_Panel, attributesPanelId = "Shop",Exclusive = true - Button: tag
UI_Button, attributesAction = "TogglePanel",TargetPanel = "Shop"
Use Action = "ClosePanel" (with the same TargetPanel) for a dedicated close button inside the panel. If you omit TargetPanel on a ClosePanel button, it closes the nearest ancestor panel — handy for a generic X button.
Icon hover effect: if the button contains a descendant tagged GeneralUIKit_ButtonIcon, that icon scales up slightly on hover and back on leave. The icon is located by tag anywhere inside the button, not by name.
UI_Animated
A decorative UI element with a looping animation.
| Attribute | Type | Required | Description |
|---|---|---|---|
Animation | string | Yes | "Rotate" (continuous spin) or "HoverBob" (gentle float on hover). |
Speed | number | No | Duration in seconds of one full rotation — larger values spin slower. Default: 15. Only used by Rotate; ignored by HoverBob. |
UI_Tooltip
A shared tooltip frame. There is one tooltip per type, registered by its TooltipType attribute — every UI_Button with ShowTooltip uses the single Button tooltip, and every UI_EffectIcon uses the single Effect tooltip. You do not create a tooltip per button.
| Attribute | Type | Required | Description |
|---|---|---|---|
TooltipType | string | Yes | "Button" (follows the cursor near a hovered button) or "Effect" (anchors beside a hovered effect icon, with screen-edge bounds checking). |
Tooltip content contract. GUIManager fills tooltip text by locating descendants by tag — anywhere inside the tooltip frame, not by name:
| Tag | Where | Purpose |
|---|---|---|
GeneralUIKit_ButtonNameLabel | Inside the Button tooltip | TextLabel that receives the button's TooltipText. |
GeneralUIKit_EffectNameLabel | Inside the Effect tooltip | TextLabel that receives the effect icon's Name. |
GeneralUIKit_EffectDescriptionLabel | Inside the Effect tooltip | TextLabel that receives the effect icon's Description. |
GeneralUIKit_ButtonIcon | Inside a UI_Button | Icon that scales up on hover. |
UI_EffectIcon
An icon representing a buff or game effect. Hovering it shows the shared Effect tooltip with the icon's Name as the title and Description as the body.
| Attribute | Type | Required | Description |
|---|---|---|---|
Description | string | Yes | Text displayed in the Effect tooltip on hover. |
UI_TypeSound
Apply to a TextBox to play a typing sound as the player types. The sound plays only when the text gets longer — backspace and deletions are silent. No attributes required.
UI_DataBind
Apply to a TextLabel or TextButton to live-bind its text to player data. The label updates automatically whenever the bound value changes — no polling, no manual refresh.
| Attribute | Type | Required | Description |
|---|---|---|---|
DataPath | string | Yes | Dot-path into the replicated PlayerData folder, e.g. Stats.Cash. |
Prefix | string | No | Text prepended to the value, e.g. "$". |
Suffix | string | No | Text appended to the value, e.g. " pts". |
Format | string | No | Number formatting: Default (raw), Short (12.5K, 3.2M, 1.1B…), Full (floored integer), Commas (1,250,000). Non-numeric values are shown as-is. |
Example: a cash counter in your HUD.
- TextLabel: tag
UI_DataBind, attributesDataPath = "Stats.Cash",Prefix = "$",Format = "Short"
Registering Button Handlers
Call GUIBridge.registerHandlers from a LocalScript that runs after the GUI loads.
local GUIBridge = require(ReplicatedStorage.RBLXEssentials.EcosystemCore.Shared.GUIBridge)
GUIBridge.registerHandlers({
OpenShop = function(button)
GUIBridge.getPanel("Shop").Visible = true
end,
BuyItem = function(button)
local productId = button:GetAttribute("ProductId")
game:GetService("MarketplaceService"):PromptProductPurchase(
game.Players.LocalPlayer, productId
)
end,
})
Built-in Actions
These actions are handled by GUIManager directly. Do not register handlers for them.
| Action | Effect |
|---|---|
TogglePanel | Toggles the panel named in TargetPanel. |
ClosePanel | Closes the panel named in TargetPanel, or the button's nearest ancestor panel if TargetPanel is unset. |
InviteFriends | Prompts the SocialService friend-invite dialog (permission-checked; fails silently if invites aren't available). |
Notes
- Sound System is required. GUIManager and the typing-sound listener require
SFXSystemdirectly — install Sound System alongside this pack. Only the effect-tooltip listener degrades gracefully without it. - Every
GuiButtonin the GUI is automatically wired for click and hover sounds — no tag needed. To exclude a button (e.g. an invisible click blocker), name itBLOCK. - Tooltips are throttled at 16ms intervals to avoid layout thrashing.
- All GUIManager connections are cleaned up via Trove when the GUI is destroyed (respawn/reload safe).
Easy Leaderstats & Leaderboards System
PackId: EasyLeaderstatsSystem · Version: 1.0.4 (requires plugin 1.0.7 or newer for the leaderboard template dropdown) · Dependencies: Datastore & Purchase System
What It Does
Easy Leaderstats & Leaderboards System adds two related features to your game:
- Leaderstats: the in-game stat list shown in the Tab/escape menu. Values are read directly from player data (provided by the Datastore & Purchase System) and kept in sync automatically.
- Global Leaderboards: physical in-world boards that display the all-time top players for any stat, stored in Roblox
OrderedDataStores and refreshed on a configurable interval.
Both features are fully configuration-driven from the plugin. No script editing is needed to add or remove stats and leaderboards.
Plugin Configuration
Selecting the pack in the plugin opens a settings panel with two sections: Leaderstats and Leaderboards.
Leaderstats
Each stat entry corresponds to one row in the Tab menu. Entries are grouped by the data group they belong to (e.g. Stats).
| Field | Description |
|---|---|
DisplayName | Label shown in the Tab menu (e.g. Cash, Wins). |
Order | Sort order within the stat list. Lower numbers appear first. |
DataKey | Dot-path into PlayerData (e.g. Stats.Cash). Read-only; derived from Datastore Default Data. |
DisplayFormat | Optional formatting keyword applied to the raw number (see the keyword table below). If empty, Default is used. |
Prefix | Optional text prepended to the displayed value (e.g. $). |
Suffix | Optional text appended to the displayed value (e.g. wins). |
DisplayFormat accepts these keywords (not printf-style format strings):
| Keyword | Behaviour |
|---|---|
Default | Raw number, displayed as-is. |
Short | Abbreviated with a suffix tier: 1.5K, 2.3M — tiers go K, M, B, T, Qa, Qi. |
Full | Floored integer (52500.9 → 52500). |
Commas | Thousands separators (52500 → 52,500). |
These fields compose left-to-right: Prefix + formatted value + Suffix. When a Prefix or Suffix is set and the format is Default, the value is formatted as Full (a floored integer string) so the affix can wrap it.
| DisplayFormat | Prefix | Suffix | Raw value | Result |
|---|---|---|---|---|
Default | (empty) | (empty) | 52500 | 52500 |
Short | (empty) | (empty) | 52500 | 52.5K |
Short | (empty) | (empty) | 2300000 | 2.3M |
Commas | $ | (empty) | 52500 | $52,500 |
Default | $ | (empty) | 52500.9 | $52500 (treated as Full because a prefix is set) |
Full | (empty) | wins | 7 | 7 wins |
+ Add Stat creates a new entry. The DataKey is selected from the existing variables in your Datastore Default Data, so stats must be defined there first.
Leaderboards
Global Settings
| Setting | Default | Description |
|---|---|---|
RefreshInterval | 60 | Seconds between board refreshes. |
MaxEntries | 50 | Maximum rows shown per board. |
Leaderboards
Each entry drives one physical in-world leaderboard board. Boards are discovered via the CollectionService tag ELS_Leaderboard: any Model in workspace with that tag and an ELS_LeaderboardId attribute appears here automatically. Models can be placed anywhere in the workspace hierarchy.
| Field | Description |
|---|---|
StatPath | Dot-path into PlayerData for the stat this board tracks (e.g. Stats.Cash). Changing this renames the board automatically. |
Template | Which template model to use — a dropdown listing the models in ServerStorage/.../Templates/. Changing it swaps the in-world model while preserving its position and orientation. |
ValueFormat | How values are displayed: Raw (52500), Comma (52,500), or Abbreviated (52.5K). |
Enabled | When OFF, this leaderboard is skipped entirely. |
+ Add Leaderboard clones the first template from ServerStorage/.../Templates/, places it in workspace.EasyLeaderstatsSystem, assigns a GUID, and creates the corresponding Settings entry. The new model is selected in Studio automatically.
Delete Leaderboard removes both the Settings entry and the workspace model.
Duplicating a Board in Studio
If you duplicate a leaderboard Model in Studio, the plugin detects the duplicate GUID and automatically assigns the clone a new unique ID and a new Settings entry.
Uninstalling
Removes the pack's deployed folders from all service locations. The pack template stays in ServerStorage so you can reinstall at any time.
That's everything from the plugin.
The sections below cover how the system works under the hood and what runtime behaviour to expect.
How It Works
Leaderstats
On server start, Bootstrap.server.lua creates a leaderstats folder under each player as they join, then creates one leaderstat per configured entry. The value is read from PlayerData using the DataKey dot-path and a changed signal keeps it in sync throughout the session.
The leaderstat type follows the source value in PlayerData:
| Source type | Leaderstat created |
|---|---|
IntValue / NumberValue | IntValue — or StringValue when a custom DisplayFormat, Prefix, or Suffix is set, so the formatted text can be displayed. |
StringValue | StringValue — Prefix/Suffix are still applied to the string. |
BoolValue | BoolValue — shown as true/false. |
Global Leaderboards
Stats are written to OrderedDataStores in three situations:
- On join: once PlayerData is loaded and all configured stat values are non-nil, stats are written. Polls up to 10 seconds waiting for data readiness.
- On leave: stats are written immediately when the player disconnects.
- Periodically: every 5 minutes, all current players' stats are written to keep leaderboard data fresh for long sessions.
Board UI is refreshed every RefreshInterval seconds. The first refresh runs 5 seconds after server start to allow player data to load. During each refresh, the top MaxEntries players are read from the OrderedDataStore and the SurfaceGui list on the in-world board is rebuilt. A countdown timer on each board shows when the next refresh will occur.
Per-board display settings have sensible fallbacks, all derived from the last segment of StatPath (e.g. Stats.Cash → Cash):
- Empty
TitleLabelText→TOP <STAT>(e.g.TOP CASH). - Empty
VariableNameText→<STAT>(e.g.CASH). - Empty or unrecognized
ValueFormat→Raw.Abbreviatedcovers the K, M, and B tiers.
OrderedDataStore Naming
Store names are derived automatically from the stat path: GlobalLeaderboard_ followed by the dot-path with dots replaced by underscores.
-- e.g. Stats.Cash → GlobalLeaderboard_Stats_Cash
Inspecting the raw store: values are stored with a +1 offset (subtracted back on read), so a stored 52501 means the player's stat is 52500. Stats ≤ 0 are not written to the store at all.
Dummy Avatars
The top 3 players on each board have their Roblox avatar applied to Dummy1, Dummy2, and Dummy3 models placed beside the board. Avatars are scaled down and play looping emote animations. Avatar application is skipped for a rank if the same player holds that rank after a refresh; only changed ranks trigger a new GetHumanoidDescriptionFromUserId call.
Settings Structure
All settings live under ServerStorage/RBLXEssentials/EasyLeaderstatsSystem/Settings/.
Settings/
├── Leaderstats/
│ └── [GroupName]/
│ └── [StatName]/ — one folder per stat
│ ├── DataKey StringValue dot-path into PlayerData (read-only)
│ ├── DisplayName StringValue label shown in Tab menu
│ ├── Order NumberValue sort order
│ ├── DisplayFormat StringValue Default | Short | Full | Commas
│ ├── Prefix StringValue optional prefix text
│ └── Suffix StringValue optional suffix text
└── Leaderboards/
├── RefreshInterval NumberValue seconds between refreshes (default: 60)
├── MaxEntries NumberValue max rows per board (default: 50)
└── [EntryName]/ — one folder per leaderboard
├── StatPath StringValue dot-path into PlayerData
├── Template StringValue name of template in Templates/ folder
├── Enabled BoolValue if false, board is skipped
├── ValueFormat StringValue Raw | Comma | Abbreviated
├── TitleLabelText StringValue text shown on TopPart title label
└── VariableNameText StringValue column header text on the board list
The pack ships three board template models in a separate folder alongside Settings:
ServerStorage/RBLXEssentials/EasyLeaderstatsSystem/
├── Settings/
├── Templates/
│ ├── LeaderboardTemplate1 [Model]
│ ├── LeaderboardTemplate2 [Model]
│ └── LeaderboardTemplate3 [Model]
└── ...
Each leaderboard Settings folder also has an ELS_LeaderboardId attribute (GUID string) that links it to its workspace model.
In-World Board Setup
Each board is a Model anywhere in workspace tagged with ELS_Leaderboard (CollectionService). New boards are cloned from the template selected in the board's Template setting (a model inside ServerStorage/RBLXEssentials/EasyLeaderstatsSystem/Templates/) and placed inside workspace.EasyLeaderstatsSystem for organisation (the folder is created automatically if it doesn't exist). Changing the Template setting later swaps the in-world model in place, preserving its position and orientation.
The system locates UI elements by ELS_Role attribute, not by path, so the internal hierarchy of the model can vary between templates.
[StatPath leaf] Leaderboard [Model]
├── BoardModel
│ ├── BoardBase [Part]
│ │ └── Leaderboard [SurfaceGui]
│ │ ├── Rank [TextLabel, header] ELS_Role = HeaderRank
│ │ ├── Name [TextLabel, header] ELS_Role = HeaderName
│ │ ├── Value [TextLabel, header] ELS_Role = HeaderValue (shows VariableNameText)
│ │ └── List [ScrollingFrame] ELS_Role = List
│ │ └── Template [Frame, cloned per entry, must stay hidden]
│ │ └── Frame
│ │ ├── Rank, Name, Value [TextLabel]
│ │ └── Icon [ImageLabel]
│ └── TopPart [Part]
│ └── Leaderboard [SurfaceGui]
│ └── TextLabel ELS_Role = TitleLabel (shows TitleLabelText)
├── Dummy1 / Dummy2 / Dummy3 [Model, R15 rigs for top-3 avatars]
└── Timer [Part]
└── GUI [SurfaceGui]
└── Label [TextLabel, shows "Refresh in: Xs"]
ELS_Role | Element | Populated with |
|---|---|---|
TitleLabel | TextLabel on TopPart board | TitleLabelText setting (e.g. TOP CASH) |
List | ScrollingFrame containing entry rows | (used as parent for cloned entries) |
HeaderRank | Rank header TextLabel | # (static, set by template) |
HeaderName | Name header TextLabel | Player name (static, set by template) |
HeaderValue | Value header TextLabel | VariableNameText setting (e.g. CASH) |
Each board Model also carries these attributes (managed by the plugin):
| Attribute | Type | Purpose |
|---|---|---|
ELS_LeaderboardId | string (GUID) | Stable unique link to the Settings entry. |
ELS_StatPath | string | Dot-path into PlayerData (e.g. Stats.Cash). |
Requirements
- Datastore & Purchase System must be installed and providing
PlayerDatafor each player. - API Services must be enabled (Game Settings → Security → Enable Studio Access to API Services) for OrderedDataStores to work in Studio.
Changelog
Version history for all packs and the plugin.