Hello, I am creating a game with multiple different stats. (Perception, dexterity, strength, etc.)
When a player reaches a certain requirement of stats for a specific skill, they will automatically unlock the skill. I have around 30 skills right now, but there will be around 200 or so in the end.
For instance, a player will unlock a skill called “Crushing Blow” at 45 strength and 15 perception.
I am wondering, what is the most lag-free way to handle this skill unlocking? Right now, I just loop through all the skills when the players stat changes, but that obviously isn’t very optimised.
if the stats are held as intvalues in a folder, you can create an event listener for when the Value property changes, and lookup a dictionary for if they need to unlock a new skill
example:
local unlocks = {
["Strength"] = {[5]="Ability1",[10]="Ability2"}
}
for _, stat in pairs(statFolder:GetChildren()) do
stat:GetPropertyChangedSignal("Value"):Connect(function()
local unlockedAbility = unlocks[stat.Name][stat.Value]
if unlockedAbility then
-- give the new ability
end
end)
end
in that case im not sure if there is any better way of finding out if the player unlocks any new skills, the only optimisation i can think of is only iterating over skills that the player hasnt already unlocked
Only check reqs for unobtained skills and only check the required stats instead of looping over all of them. As long as you’re doing that then there’s no quicker way to verify what skills the player needs to be awarded.
You can put a task.spawn(function() and a end) in the for loop which will start new threads for every skill, so they can update at the same time, idk if that’s as efficient as ur original core tho
Sounds like an observer for your character attributes.
All you have to do is to loop through them once, stablish a changed connection and check for their values. The other ways are the inefficient ones, from my point of view, as long as you run once, create the connections and clean them up when the player leaves, you’re already doing it the most efficient way.
There is another way though, which is a condition placed in the function/event you use to change those attributes.
-- this
local function OnPlayerAdded(player)
for _, v in attributes:GetChildren() do
local limit = attributeLimits[v.Name]
if v.Value >= limit then continue end
local event
event = v.Changed:Connect(function(newValue: number)
if newValue >= limit then
event:Disconnect();
event = nil
unlockSkill()
end
end)
end
end
Players.PlayerAdded:Connect(OnPlayerAdded)
-- or this
local function addStrength(value)
local strength = ...
strength += value
if strenth >= limit then
unlockStrengthSkill()
end
end