Hello, i’m trying to make a system so when you collect coins instead switching instantly to the new value it tells you how much got added and smoothly starts increasing until the change is 0.
Right now when i collect two seperate coins it adds the first one and then adds the second one, i want them both to be added at the same time.
Like Hollow Knight
The script:
local text = script.Parent
local plr = game:GetService("Players").LocalPlayer
local added = text.Parent:WaitForChild("Added")
local coins = plr:WaitForChild("Coins")
local rs = game:GetService("RunService")
local old = coins.Value
local timeWait = 0
local change = 0
text.Text = old
coins.Changed:Connect(function(new)
change = new - old
if change > 0 then
change = new - old
added.Visible = true
timeWait += 2
added.Text = "+" .. change
task.wait(timeWait)
if timeWait > 2 then
task.wait(timeWait)
end
while wait(0.05) do
old += 1
change -= 1
text.Text = old
added.Text = "+" .. change
if old == new then
old = new
timeWait = 0
text.Text = new
added.Visible = false
break
end
end
end
if change < 0 then
change = new - old
added.Visible = true
timeWait += 2
added.Text = "-" .. change
task.wait(timeWait)
if timeWait > 2 then
task.wait(timeWait)
end
while wait(0.05) do
old -= 1
change += 1
text.Text = old
added.Text = "-" .. change
if old == new then
old = new
timeWait = 0
text.Text = new
added.Visible = false
break
end
end
end
end)
The basics of how I would approach this is by simply keeping a variable in the UI that is “display coins” seperate from the actual coin value. Every frame the “display coins” is shifted closer to the actual coin value. For all intents and purposes the actual coin value represents your coins at any time, this display value only exists on the client as part of their UI.
So for example, we start with 0 coins and set display_coins to the same. Every frame we do a single check if display_coins ~= coins. In this case we shift display_coins. There are a few ways to do this. I think logrthmic scaling is fun, so that at the start the change is fast and slows down till it reaches the goal but let’s start simple with linear scaling.
local RunService = game:GetService("RunService") -- Get the RunService.
local text = script.Parent -- Get your text label.
local plr = game:GetService("Players").LocalPlayer -- Get the local player!
local coinVal = plr:WaitForChild("Coins") -- Get your value that contains the coins.
local display_coins = coinVal.Value -- No need to do this effect at the start. Just set them equal.
RunService.RenderStepped:Connect(function(step)
if display_coins ~= coins then
local sign_value = ((coinVal.Value - display_coins) < 0 and -1) or 1 --[[ To explain this, we check if the difference in values is less than zero,
if it is the AND condition is evaluated and -1 is returned, otherwise since it's false we jump to the OR condition and 1 is returned.
In short this gets us -1 or 1 based on if the difference is positive or negative. ]]
display_coins += sign_value -- Add or subtract 1 to move the display value closer to the actual value.
text.Text = display_coins -- Update the text.
end
end)
You can add delay tracking in here so it doesn’t update as fast (currently updates 1 per frame, but you could simply have a tracking value that increments each frame and whenever it hits a certain value reset it and adjust the display_coins to do things like once every 3 frames). Also again you can do non-linear adjustments so that the value quickly moves then slows down as it gets closer, but that’s all up to you. I also didn’t bother including code for the display of the “+x” or “-x” which should probably fire off seperate than the display updating in my opinion.