Solved

[Unity] Display monthly price of a annual subscription

  • 26 December 2022
  • 4 replies
  • 201 views

Userlevel 2
Badge +5

As far as I can see, there is no property or method to directly get the monthly price of an annual subscription in Unity.

I found this thread from a month ago with the same issue, but everything discussed in there only applies for the native Android and iOS SDKs: 

 

How do we calculate this in Unity and show the currency symbol in the correct position (some countries have it before and same after the price)?

icon

Best answer by Michael Fogel 28 December 2022, 23:47

View original

4 replies

Userlevel 4
Badge +6

Hey Maru, 

 

Unfortunately we dont have an easy way to do this as of now but I will pass this along to the team. However I can suggest a possible workaround to get this done but you would have to do it programmatically on your end. 

 

What I would do is get the products price from the StoreProduct object and then divide that price by 12. The only problem with this would be that you can run into issues like dealing with all of the global currencies and localized styles (e.g. 10,00 vs 10.00).

 

I know Unity has a build in localization package which might work to help solve this, but I am not sure. I would recommend trying to use this combined with the price and then dividing that by 12 and displaying that price as the “Monthly” version of the “Annual” price. 

Badge +4

Is this coming in the near future? 

Badge +2

This would be a nice feature to have. It’s pretty common to show what the monthly cost breaks down to for different subscription lengths and with all the different currency formats out there it’s difficult to properly format it even if we convert the amount ourselves.

Badge +3

+1 for this, almost every game will need this.

For anyone interested, I think I found a good way that does not require any manual mapping or hardcoding of currencies (not tested extensively yet)

  • Take the ISO4217 CurrencyCode from a StoreProduct
  • Look through all CultureInfos in C# System.Globalization, find the ones where Region.ISOCurrencySymbol matches the CurrencyCode
  • Because a lot of currencies are used in multiple Regions, I try to default to the one that matches the CultureInfo on the device (which in Unity, to my knowledge, you have to get from LocalizationSettings.SelectedLocale.Identifier.CultureInfo)
  • Now that we have the CultureInfo that matches the CurrencyCode, we can use C#s ToString("C", cultureInfo) to properly format the price in the currency (which will place the right symbol on the right spot, use the correct delimiters, etc)
  • With this in place, we can use the price float on the StoreProduct to calculate whatever the monthly cost of this option would be. I use PackageType of the returned RevenueCat package to determine the billing interval

Here is the central method for this approach:

public static CultureInfo GetCultureInfoForCurrency(string ISOCurrencySymbol, CultureInfo currentCulture)
{
// Get all specific cultures that have a RegionInfo, avoiding exceptions by checking the culture's name
var allCulturesWithRegion = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
.Select(culture => string.IsNullOrWhiteSpace(culture.Name) ? null : new { Culture = culture, Region = new RegionInfo(culture.Name) })
.Where(x => x != null && x.Region.ISOCurrencySymbol == ISOCurrencySymbol)
.ToList();

Debug.Log($"CurrencyHelper.GetCultureInfoForCurrency: Found {allCulturesWithRegion.Count} cultures for currency {ISOCurrencySymbol}");

// Attempt to find a culture that matches the device's current culture
var matchingCulture = allCulturesWithRegion
.FirstOrDefault(x => x.Culture.Name.Equals(currentCulture.Name, StringComparison.OrdinalIgnoreCase));

// If no exact match is found, just pick the first one
if (matchingCulture == null)
{
matchingCulture = allCulturesWithRegion.FirstOrDefault();
}

if (matchingCulture != null)
{
Debug.Log($"CurrencyHelper.GetCultureInfoForCurrency: Found matching culture: {matchingCulture.Culture}");
return matchingCulture.Culture;
}
else
{
return null;
}
}

 

Reply