diff --git a/README.md b/README.md index 910a7110..9ef602e9 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ ### 1: Download the repo and drop it into folder `Assets` ### 2: Add the line below to `Packages/manifest.json` -for version `3.2.2` +for version `3.2.3` ```csharp -"com.virtuesky.sunflower":"https://github.com/VirtueSky/sunflower.git#3.2.2", +"com.virtuesky.sunflower":"https://github.com/VirtueSky/sunflower.git#3.2.3", ``` ## Includes modules diff --git a/VirtueSky/ControlPanel/ConstantPackage.cs b/VirtueSky/ControlPanel/ConstantPackage.cs index feb8b5eb..38e7a042 100644 --- a/VirtueSky/ControlPanel/ConstantPackage.cs +++ b/VirtueSky/ControlPanel/ConstantPackage.cs @@ -2,7 +2,7 @@ { public class ConstantPackage { - public const string VersionSunflower = "3.2.2"; + public const string VersionSunflower = "3.2.3"; public const string PackageNameInAppPurchase = "com.unity.purchasing"; public const string MaxVersionInAppPurchase = "4.12.2"; public const string PackageNameNewtonsoftJson = "com.unity.nuget.newtonsoft-json"; diff --git a/VirtueSky/Core/Runtime/UnityServiceInitialization.cs b/VirtueSky/Core/Runtime/UnityServiceInitialization.cs new file mode 100644 index 00000000..b1a2badc --- /dev/null +++ b/VirtueSky/Core/Runtime/UnityServiceInitialization.cs @@ -0,0 +1,33 @@ +using Unity.Services.Core; +using Unity.Services.Core.Environments; +using UnityEngine; + +namespace VirtueSky.Core +{ + public class UnityServiceInitialization : MonoBehaviour + { + private enum Environment + { + Production, + Development, + } + + [SerializeField] private Environment environment = Environment.Production; + + public static bool IsUnityServiceReady { get; private set; } + + private void Awake() + { + Init(); + } + + private async void Init() + { + IsUnityServiceReady = false; + var options = new InitializationOptions(); + options.SetEnvironmentName(environment.ToString().ToLower()); + await UnityServices.InitializeAsync(options); + IsUnityServiceReady = true; + } + } +} \ No newline at end of file diff --git a/VirtueSky/Core/Runtime/UnityServiceInitialization.cs.meta b/VirtueSky/Core/Runtime/UnityServiceInitialization.cs.meta new file mode 100644 index 00000000..bbbd2c35 --- /dev/null +++ b/VirtueSky/Core/Runtime/UnityServiceInitialization.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cc3bfe5d4d6342a28dc707cf2416ee41 +timeCreated: 1734073870 \ No newline at end of file diff --git a/VirtueSky/Core/Runtime/virtuesky.sunflower.core.asmdef b/VirtueSky/Core/Runtime/virtuesky.sunflower.core.asmdef index 4653e68a..3ac711fa 100644 --- a/VirtueSky/Core/Runtime/virtuesky.sunflower.core.asmdef +++ b/VirtueSky/Core/Runtime/virtuesky.sunflower.core.asmdef @@ -3,7 +3,9 @@ "rootNamespace": "", "references": [ "GUID:32dbaa332e571bf429b7de517f75f074", - "GUID:324caed91501a9c47a04ebfd87b68794" + "GUID:324caed91501a9c47a04ebfd87b68794", + "GUID:fe25561d224ed4743af4c60938a59d0b", + "GUID:70ea675efa2644cef98c7ece24158333" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/VirtueSky/Iap/Runtime/IapDataVariable.cs b/VirtueSky/Iap/Runtime/IapDataVariable.cs index 03b34e61..3666e483 100644 --- a/VirtueSky/Iap/Runtime/IapDataVariable.cs +++ b/VirtueSky/Iap/Runtime/IapDataVariable.cs @@ -16,18 +16,12 @@ public class IapDataVariable : ScriptableObject [Space] public float price; [SerializeField] private IapPurchaseSuccess onPurchaseSuccess; [SerializeField] private IapPurchaseFailed onPurchaseFailed; - - [ReadOnly] internal Product product; - [ReadOnly] internal SubscriptionInfo subscriptionInfo; internal IapPurchaseSuccess OnPurchaseSuccess => onPurchaseSuccess; internal IapPurchaseFailed OnPurchaseFailed => onPurchaseFailed; [NonSerialized] public Action purchaseSuccessCallback; [NonSerialized] public Action purchaseFailedCallback; - public Product Product => product; - public SubscriptionInfo SubscriptionInfo => subscriptionInfo; - private IapManager iapManager; internal void InitIapManager(IapManager _iapManager) @@ -35,6 +29,18 @@ internal void InitIapManager(IapManager _iapManager) iapManager = _iapManager; } + public Product GetProduct() + { + if (iapManager == null) return null; + return iapManager.GetProduct(this); + } + + public SubscriptionInfo GetSubscriptionInfo() + { + if (iapManager == null) return null; + return iapManager.GetSubscriptionInfo(this); + } + public void Purchase() { iapManager.PurchaseProduct(this); diff --git a/VirtueSky/Iap/Runtime/IapManager.cs b/VirtueSky/Iap/Runtime/IapManager.cs index d1412553..f5e89e9f 100644 --- a/VirtueSky/Iap/Runtime/IapManager.cs +++ b/VirtueSky/Iap/Runtime/IapManager.cs @@ -1,7 +1,6 @@ #if VIRTUESKY_IAP using System; -using Unity.Services.Core; -using Unity.Services.Core.Environments; +using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Purchasing; using UnityEngine.Purchasing.Extension; @@ -28,7 +27,7 @@ public class IapManager : BaseMono, IDetailedStoreListener private IStoreController _controller; private IExtensionProvider _extensionProvider; private static event Action RestoreEvent; - public static bool IsInitialized { get; set; } + public static bool IsInitialized { get; private set; } public static void Restore() => RestoreEvent?.Invoke(); private void Awake() @@ -61,21 +60,13 @@ private void Start() } private async void Init() - { - var options = new InitializationOptions().SetEnvironmentName("production"); - await UnityServices.InitializeAsync(options); - InitImpl(); - } - - void InitImpl() { if (IsInitialized) return; + await UniTask.WaitUntil(() => UnityServiceInitialization.IsUnityServiceReady); var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance()); RequestProductData(builder); builder.Configure(); - UnityPurchasing.Initialize(this, builder); - IsInitialized = true; } #region Internal Api @@ -89,11 +80,24 @@ internal bool IsPurchasedProduct(IapDataVariable product) internal void PurchaseProduct(IapDataVariable product) { - // call when IAPDataVariable raise event if (changePreventDisplayAppOpenEvent != null) changePreventDisplayAppOpenEvent.Raise(true); PurchaseProductInternal(product); } + internal Product GetProduct(IapDataVariable product) + { + if (_controller == null) return null; + return _controller.products.WithID(product.id); + } + + internal SubscriptionInfo GetSubscriptionInfo(IapDataVariable product) + { + if (_controller == null || product.productType != ProductType.Subscription || !_controller.products.WithID(product.id).hasReceipt) return null; + var subscriptionManager = new SubscriptionManager(GetProduct(product), null); + var subscriptionInfo = subscriptionManager.getSubscriptionInfo(); + return subscriptionInfo; + } + #endregion #region Implement @@ -136,14 +140,12 @@ public void OnInitialized(IStoreController controller, IExtensionProvider extens _controller = controller; _extensionProvider = extensions; -// #if UNITY_ANDROID && !UNITY_EDITOR -// foreach (var product in _controller.products.all) -// { -// if (product != null && !string.IsNullOrEmpty(product.transactionID)) _controller.ConfirmPendingPurchase(product); -// } -// #endif + foreach (var iapDataVariable in iapSetting.Products) + { + iapDataVariable.InitIapManager(this); + } - InitProductIapDataVariable(); + IsInitialized = true; } public void OnInitializeFailed(InitializationFailureReason error, string message) @@ -181,22 +183,6 @@ public void OnPurchaseFailed(Product product, PurchaseFailureDescription failure #endregion - - private void InitProductIapDataVariable() - { - foreach (var iapDataVariable in iapSetting.Products) - { - iapDataVariable.InitIapManager(this); - var product = _controller.products.WithID(iapDataVariable.id); - iapDataVariable.product = product; - if (iapDataVariable.productType == ProductType.Subscription) - { - var subManager = new SubscriptionManager(product, null); - iapDataVariable.subscriptionInfo = subManager.getSubscriptionInfo(); - } - } - } - private IapDataVariable PurchaseProductInternal(IapDataVariable product) { #if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR diff --git a/VirtueSky/Iap/Runtime/Virtusky.Sunflower.Iap.asmdef b/VirtueSky/Iap/Runtime/Virtusky.Sunflower.Iap.asmdef index 3b4ce456..3b7c0e81 100644 --- a/VirtueSky/Iap/Runtime/Virtusky.Sunflower.Iap.asmdef +++ b/VirtueSky/Iap/Runtime/Virtusky.Sunflower.Iap.asmdef @@ -11,10 +11,9 @@ "GUID:08d1c582746949b40ba6a45cdb776bdf", "GUID:fca7ec166e04dc948b624a983315e2c9", "GUID:a90b00dc83a89964cb7641c304492d29", - "GUID:fe25561d224ed4743af4c60938a59d0b", - "GUID:70ea675efa2644cef98c7ece24158333", "GUID:c904f6d969e991d459a0843b71c22ec5", - "GUID:324caed91501a9c47a04ebfd87b68794" + "GUID:324caed91501a9c47a04ebfd87b68794", + "GUID:f51ebe6a0ceec4240a699833d6309b23" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/package.json b/package.json index 9b5e654d..10564ca4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "com.virtuesky.sunflower", "displayName": "Sunflower", "description": "Core ScriptableObject Architecture for building Unity games", - "version": "3.2.2", + "version": "3.2.3", "unity": "2022.3", "category": "virtuesky", "license": "MIT",