How can I make Text smoothly change when the Value is changed

Hello! I am wondering how I can make something where when you collect a Coin, the leaderstat TextLabel on the side changes, but it changes smoothly when it goes up, instead of all boring text just changing. For example, how Pet Simulator X does it, when you get a ton of something, it smoothly and quickly changes up to the new value, instead of it just instantly changing. How can I achieve this?

This is the script that it uses to change, but I want it to change smoothly

while wait() do
	    local player = game.Players.LocalPlayer
		local Short = require(game.ReplicatedStorage.Short)
    script.Parent.Text = " "..Short.en(player:WaitForChild("leaderstats"):FindFirstChild("Money").Value)
 end

Video on what I mean:

Thanks! Any help will be appreciated! :grinning_face_with_smiling_eyes:

2 Likes

Any help will be appreciated! If you have any questions about what I mean, just ask!

To clarify, do you mean that you add like +100 to some value, and you want the TextLabel to increase the value it shows by +1 at a consistent rate, until the TextLabel’s shown value matches the underlying data value?


This is what I mean

Right. The easiest way would be to have a loop that’s always running that tries to move the textlabel’s value towards the target:

local target = 100 -- this could be your leaderstat value object or whatever
local SPEED = 25 -- points per second to approach the target
local textLabel = -- ... your text label

local shown = target -- what the text label shows. the loop changes this
while true do
  local waitedFor = task.wait(DELAY)
  local difference = target - shown
  local amount = SPEED * waitedFor
  if math.abs(difference) <= amount then
    shown = target
  else
    if shown < target then shown += amount
    else shown -= amount end
  end

  textLabel.Text = tostring(shown)
end  

Do I need to change anything inside the Script? And do I put it inside a different script, or do I put it in the same one that I included up above.

Also I get this error


And what does Target mean? What do you mean by

-- this could be your leaderstat value object or whatever

(EDIT: I have to go to bed, so I will respond when I can)

Yes you do need to change things! I was giving you a general idea of what the script might look like, not a complete solution!

The most helpful thing would be to read through it and try to figure out what it’s doing. That way you can fix it and change it in the future, too.

Put it wherever you want! I suppose it would replace the script you posted, but I don’t really know what your Short module does so you might need to add it to our script depending on what you need.

I mean that instead of 100, you should use your leaderstat object: player:WaitForChild("leaderstats"):FindFirstChild("Money") I guess in your case.

You also would need to change everywhere that target is used to target.Value.

If you make those changes, it might be a working script. Or I might’ve made a typo that broke it. Try to fix it yourself by reasoning through what it’s supposed to do :slight_smile: I’ll edit my original post with a few more comments to make your life easier.

The Short basically just adds abbreviations, such as 10M, or 10,000, etc. and where does Target go? I don’t think you said that. Also never mind that, I am really blind, you stated to change it to that. Sorry about that, I am on my phone. Apologies

Since you’re a beginner, I think it’s worth it to have you do the fixing up yourself! I modified the above script slightly. It still won’t work out of the box, but I commented every line. Look for the “REPALCE” comments and try to fill in the values.

This script, once you patch it, will replace the one you posted.

-- First, we set up some variables that you can change

-- REPLACE  ... with your leaderstat object (that would be player:WaitForChild("leaderstats"):FindFirstChild("Money") in your case)
local target = ...

-- REPLACE ... with how fast you want the label to update
-- For example, if this is 25, the text label with go towards the target at 25
-- money per second
local SPEED = ...

-- REPLACE ... with how long to wait between updating the TextLabel
-- For example, if your SPEED was 25 and your DELAY is 2, your TextLabel will jump
-- about 50 moneys every 2 seconds.
local DELAY = ...

-- REPLACE the ... with your TextLabel object (that would be script.Parent in your case)
local textLabel = ...

-- `shown` is a number representing what the TextLabel is currently showing.
-- At first, we just show the same thing as the leaderstats.
local shown = target.Value

-- `while true do` means: do this forever
while true do

  -- We wait a little bit. `waitedFor` gives us how many seconds we ACTUALLY waited for,
  -- since it's not always exact
  local waitedFor = task.wait(DELAY)

  -- Figure out how much we need to change IN TOTAL. If our `target` is
  -- 10, but our `shown` is 50, our difference is -40
  local difference = target.Value - shown

  -- Figure out how much we need to change THIS UPDATE. If our speed is 25, and
  -- we waited for 2 seconds, we want to change by 50 moneys
  local amount = SPEED * waitedFor

  -- Check if we are really close to the amount. math.abs() just removes the
  -- negative sign.
  -- For example, if our difference is 40 but we want to change by 50 moneys, this
  -- is true:
  if math.abs(difference) <= amount then

    -- We're close enough. Just display the real value!
    shown = target.Value

  -- This `else` means we are showing a value that's really different from the
  -- target
  else

    -- If we're below the target, add the amount we calculated before (e.g. 50)
    if shown < target.Value then shown += amount

    -- If we're above the target, subtract it
    else shown -= amount end
  end

  -- Whatever happened, our text label should always be in sync with the `shown`
  -- variable
  -- REPLACE with you `Short` module calculation or something, but use somethign like
  -- Shown.en(shown)
  textLabel.Text = tostring(shown)

end

one of the common issues usually forgotten when the constant rate of addition is always at a specific value and doesn’t get larger depending on how much you have is that it probably takes a long time

if you don’t get what i mean basically the coin per second constant rate is 1000 but you have 100k, it’ll take basically 100 seconds so besides only making the text smoothly change, multiply the constant rate 1/5th of your initial collected things so if you have like 1 sasmillion it’ll give 0.2 sasmillion every second

The best way to do this is using TweenService. Using infinite loops is an extremely bad practice - it is poor for performance and may break your game.

The code below will smoothly animate your text whenever the value of the player’s money updates. The advantage in using this is that it’s event-based, and allows you to have different easing styles.

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

local TIME = 1 -- Time in seconds
local EASINGSTYLE = Enum.EasingStyle.Quart -- Tween easing style
local EASINGDIRECTION = Enum.EasingDirection.InOut -- Tween easing direction

local Leaderstats = Players.LocalPlayer:WaitForChild("leaderstats")
local MoneyInt = Leaderstats:WaitForChild("Money")
local MoneyText = script.Parent

local TransitionAmount = Instance.new("IntValue") -- We create a new IntValue which represents the value of the player's money before it got changed
-- The text of the TextLabel cannot be tweened due to being a string, so we use an IntValue instead.

TransitionAmount.Value = MoneyInt.Value

MoneyInt.Changed:Connect(function(amount) -- Wait for the player's money to change
	local tween = TweenService:Create(
		TransitionAmount,
		TweenInfo.new(TIME, EASINGSTYLE, EASINGDIRECTION),
		{Value = amount}
	) -- Create a tween that changes TransitionAmount's value to the new money value.
	
	tween:Play()
end)

TransitionAmount.Changed:Connect(function(amount) -- This function will fire every time the value of TransitionAmount changes, so during the tween.
	MoneyText.Text = tostring(amount) -- Change the text of the TextLabel to the new money amount.
end)

In the video below I manually change the money value to demonstrate this method:

4 Likes

Thank you! This works above my expectations and I really do appreciate this!

1 Like

Hello! Actually I have a question, and It seems to work, but it seems to make it look laggy when you change the leaderstat, and it’s for the abbreviation script that I have which is this

while wait() do
	local player = game.Players.LocalPlayer
	local Short = require(game.ReplicatedStorage.Short)
	script.Parent.Text = " "..Short.en(player:WaitForChild("leaderstats"):FindFirstChild("Money").Value)
end

And this is what I changed in your script

local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")

local TIME = 1 -- Time in seconds
local EASINGSTYLE = Enum.EasingStyle.Quart -- Tween easing style
local EASINGDIRECTION = Enum.EasingDirection.InOut -- Tween easing direction

local Leaderstats = Players.LocalPlayer:WaitForChild("leaderstats")
local MoneyInt = Leaderstats:WaitForChild("Money")
local MoneyText = script.Parent

local TransitionAmount = Instance.new("IntValue") -- We create a new IntValue which represents the value of the player's money before it got changed
-- The text of the TextLabel cannot be tweened due to being a string, so we use an IntValue instead.

TransitionAmount.Value = MoneyInt.Value

MoneyInt.Changed:Connect(function(amount) -- Wait for the player's money to change
	local tween = TweenService:Create(
		TransitionAmount,
		TweenInfo.new(TIME, EASINGSTYLE, EASINGDIRECTION),
		{Value = amount}
	) -- Create a tween that changes TransitionAmount's value to the new money value.

	tween:Play()
end)

TransitionAmount.Changed:Connect(function(amount) -- This function will fire every time the value of TransitionAmount changes, so during the tween.
	MoneyText.Text = tostring(amount) -- Change the text of the TextLabel to the new money amount.
end)

Any help will be appreciated (By the way the short is the script inside ReplicatedStorage that makes it have the abbreviations, like 1M, 10,000, etc)

Rather than putting it in an infinite loop, you should change the abbreviation in the TransitionAmount.Changed event in the script that I sent you.

I still don’t understand what you mean, I’ve been trying to figure out how I can do this and I can’t seem to do it, no matter what I do, or change, it doesn’t do it.