Get text to 'tween' and wait be based off difference in amounts

I want my text to kinda ‘animate’ when you gain/lose cash. I have this so, and it don’t work. But my idea was that it would the text like going up and down. Instead of going from say 200, to 250 in an instant, I want it show the number going up. However, I also have a BreakNumbers module which basically gets the number and returns it with appropriate , placement, eg.

100000 = 100,000

local TextTween = TweenService:Create(CurrentAmount, TweenInfo.new(1), {Cash.Value})
TextTween:Play()
Amount.Text = BreakNumbers(TextTween)
1 Like

Did you mean { Value = number } since it takes a property-to-value mapping

2 Likes

CurrentAmount = Cash.Value tho. So if that’s the starting amount, would Value still be tweenable

1 Like

yes, it would still be tweenable

Unable to cast value to Object

local TextTween = TweenService:Create(CurrentAmount, TweenInfo.new(1), {Value = Cash.Value})
TextTween:Play()
Amount.Text = BreakNumbers(TextTween )

What is CurrentAmount? It should be an Instance. I believe you passed a number.

1 Like

It’s basically storing the original number. So when their cash increaes I check what their previous number was, and then do different stuff depending if it’s an increase or decrease

You tween a property of an instance, not a number. So you want to TweenService:Create(Cash, info, { Value = whatever })

local TextTween = TweenService:Create(Cash, TweenInfo.new(), { Value = Cash.Value })
TextTween:Play()
Amount.Text = BreakNumbers(TextTween)

Does not work.

This is similar to the other problem with tweening you had with Lighting. You can’t tween a string or a literal, so you have to tween a number value and update the string accordingly.

The number value instance is used as the instance to tween. It’s initial value is the label’s current number once any formatting has been stripped. It’s goal value in the tween is the new cash value.

Inside a listener for Cash.Changed:

local NumberVal = Instance.new( 'IntValue' )
NumberVal.Value = tonumber( UnbreakNumbers( Amount.Text ) )
NumberVal.Changed:Connect( function ( value )
    Amount.Text = BreakNumbers( value )
end )
local TextTween = TweenService:Create( NumberVal, TweenInfo.new( 1 ), { Value = Cash.Value } )
TextTween:Play()
TextTween.Completed:Connect( function ( status )
	if status == Enum.TweenStatus.Completed then
		NumberVal.Value = Cash.Value
	end
end )

Example of UnbreakNumbers:

function UnbreakNumbers( numberString )
	numberString = numberString:gsub( ',', '' )
	numberString = numberString:gsub( ' ', '' )
	return numberString
end
NumberVal.Value = tonumber( Amount.Text:gsub( ',', '' ):gsub( ' ', '' ) )

bad argument #2 (base out of range)

I’ve edited my first reply to correct the issue. The listener for TextTween to complete is included to ensure NumberVal isn’t garbage collected too early as I noticed that was an issue in testing. Try now.

Got it working with a few more changes

local CurrentAmount = Cash.Value
	
local function SetAmount()
	if Cash.Value > CurrentAmount then
		-- Money has increased, play cash animation
		CashEarnt:Play()	
		CashAnimation(CashSpawn)
	end
	
	local NumberVal = Instance.new('IntValue')
	NumberVal.Value = CurrentAmount
	
	NumberVal.Changed:Connect(function(value)
		Amount.Text = BreakNumbers(value)
	end)
	
	local TextTween = TweenService:Create(NumberVal, TweenInfo.new(), {Value = Cash.Value})
	TextTween:Play()
	
	TextTween.Completed:Connect(function(status)
		if status == Enum.TweenStatus.Completed then
			NumberVal.Value = Cash.Value
		end
	end)
	
	CurrentAmount = Cash.Value
end

Cash:GetPropertyChangedSignal('Value'):Connect(SetAmount)
SetAmount()

is this fully efficient? or is there anything there that’s not necessary?

Looks good to me. Are you aware that this only animates when money increases? In OP you mentioned both gain and loss. If you only want gain then that’s fine.

The use of CurrentAmount to store the value to save you having to undo your number breaking is good - especially if you swap out zeros for K, M, B etc. as it gets higher.

Personally I think this is the best solution to animate it. The IntValue will be appropriately garbage collected once the Tween is garbage collected after completion. Everything in there seems necessary to me.

I have a cash animation and a sound that play when your money increases. However, the text animation plays for both increase and decrease which is what I want :smiley:

That’s another thing I worry about. Memory problems. Since a new IntValue is being created on every call of the function, shouldn’t I be destroying it?

A friend of mine also said to not sure :Connect() within functions that are being connected, as that can also lead to memory problems? Is that true?

In this particular case, because your tween is kept in a local variable inside the function, and there are no hard references to it, once the tween is completed it will be garbage collected.

When the tween is garbage collected, so is its connection which holds NumberVal in a hard reference, at which point NumberVal has no parent and no remaining hard references so it too is garbage collected, removing its connection too.

If you want to be safe, then destroy both the tween and the value inside the completed connection:

TextTween.Completed:Connect(function(status)
	if status == Enum.TweenStatus.Completed then
		NumberVal.Value = Cash.Value
	end
    NumberVal:Destroy()
    TextTween:Destroy()
end)

Generally your memory leaks will come from things like putting the tween or the value instance into a table, and then forgetting about them. So long as they remain in the table as a hard reference they will not be garbage collected.

The alternative is to create the value outside of the function - in the general scope of the script, along with its connection. Either way is fine in this case.

1 Like