Search Unity

Unity IAP bug on PurchaseProcessingResult listener not cleared

Discussion in 'Unity IAP' started by winxalex, Oct 9, 2018.

  1. winxalex

    winxalex

    Joined:
    Jun 29, 2014
    Posts:
    166
    Create prefab of coin shop implementing IStoreListner
    Run one instance in one scene(init happen here), then switch to another scene with the instance of the shop, then buy Product, BuyProduct will be called from the current instance but
    PurchaseProcessingResult from first instance (which is destroyed)
    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) {

    Debug.Log("Instance ID:" + this.gameObject.GetInstanceID());//this will blow

    ProductItem productItemPurchased = SelectedProductItem;


    Main point of modularity is that what ever I implement IStoreListiner should catch events and then clear onDestroy
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Do you have a question? You need to make sure methods and variables are in scope before using them. You wan to use a singleton pattern with IAP
     
    winxalex likes this.
  3. winxalex

    winxalex

    Joined:
    Jun 29, 2014
    Posts:
    166
    I don't want to used Singleton, :D, pattern have lot of flows, but if you made API to be used that way I expected to be stated in docs. ;). Thx for quick replay.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    It is up to you to ensure that methods and objects are in proper scope before using them, as stated. It is best to have a separate IAPManager class that is available across all scenes, this is common practice. There is a sample project here that demonstrates the proper use https://forum.unity.com/threads/sample-iap-project.529555/ . Regardless, I will bring your point up to the IAP team to get their feedback also. If it turns out that we do have an issue, any potential update would go into the next release in the next couple of months.
     
  5. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Please show the code that you are using (or screenshots, when using CodeLess), and the specific error text that you are receiving. Also, a minimum project that demonstrates your issue would be quite helpful. The docs do say that the listener should be globally available, but there could be something in your code also that might be causing the unwanted behavior.
     
  6. winxalex

    winxalex

    Joined:
    Jun 29, 2014
    Posts:
    166
    Hi I'm not using Singleton pattern, I know I could then call hard code static instance in every scene or Don't destroy the scene and comm with Scriptable Events,(Unity docs were against using Don't Destroy). I've CoinShopHandler script implementing IStoreListner on GO which is prefab. I've instances in many scenes. When I saw Interface I tough that no matter in which scene I implement, it would work.I notice first instance called will wire the IStoreListener handlers. Then in another scene with another instance if you call BuyProduct, Purchase handler wouldn't be called from that instance, but from first called instance, which gameobject is already Destroyed. (see video).
    I notice this when I've ProductItem non static. I was calling BuyProduct from one instance and getting some other ProductItem and find out that it comes from the first called CoinShopHandler instance, which GO was destroyed but data wasn't :).
    Code (CSharp):
    1.    public  ProductItemValue selectedProductItemValue=new ProductItemValue();
    2.  
    3.         public  ProductItem SelectedProductItem {
    4.             get {
    5.                 return selectedProductItemValue.Value;
    6.             }
    7.             set {
    8.  
    9.                 selectedProductItemValue.Value = value;
    10.             }
    11.         }



    Screen Shot 2018-10-12 at 4.00.24 PM.png Screen Shot 2018-10-12 at 4.00.50 PM.png

    Let me know I you need more info or code... THx
     

    Attached Files:

  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Sorry, I don't follow. What is GO? Please provide a simple/minimum project (not your game) that reproduces the issue and attach it here as a zip file. An IAP Listener is only for Codeless IAP, do not mix the two. There is a sample project here that properly uses a singleton pattern https://forum.unity.com/threads/sample-iap-project.529555/
     
  8. winxalex

    winxalex

    Joined:
    Jun 29, 2014
    Posts:
    166
    GO in Unity community is well known short from GameObject. I tough video show you enough. I was wrong... Sample object has only one scene, and I have write several time that I use almost same script as in sample object, but on prefab object instantiated in several scenes.
    HOW TO: Buy product,let say non consumable, hit load scene button to load MyScene 1, which is copy of MyScene provided in orginal project. Hit Buy product let say non consumable. Enjoy.
     

    Attached Files:

  9. unityjingyao

    unityjingyao

    Unity Technologies

    Joined:
    Feb 20, 2017
    Posts:
    220
    Hi,
    When you call 'UnityPurchasing.Initialize', you must offer an instance of 'IStoreListener' and it can't be destroyed during the whole game session. Otherwise, IAP callbacks will not be invoked and you'll see that error message in your video.
    So Singleton is necessary. If you don't want to make 'MonoBehaviour' subclass as a Singleton, you can make the implementation class of 'IStoreListener' as a Singleton.
    Class 'CodelessIAPStoreListener' is a good example to show how to do that. You can find it at 'Assets\Plugins\UnityPurchasing\script\CodelessIAPStoreListener.cs'. It's used for Codeless IAP.
     
    winxalex likes this.
  10. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
  11. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    What info are you referring? A listener must always be available, that is not specific to IAP. Any service that provides a callback must have a listener available. It's generally called a singleton pattern, common to programming. The Sample IAP Project demonstrates this. If you can elaborate, we can look into making the docs more clear.
     
  12. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    I agree but not everyone likes to use the singleton pattern. You might want to start your services whenever you want to and listen. But I'm not saying you shouldn't have done it that way.
     
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You can start your services whenever you want, but you also need to keep a listener ready. Some studios wait to initialize IAP until the user is initiates a purchase to avoid a possible login dialog at the beginning of the game. But when you initialize IAP, you must be ready to handle the store callbacks.
     
  14. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    we could be discussing all day about this. if you think forcing people to use a singleton ( an anti-pattern considered by millions of coders) without even mentioning it in the docs then fine good for you, I found the help I wanted here and now I have my singleton with the dontdestroyonload because if I reload scene the whole thing messes up.
     
  15. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I'm not suggesting a singleton, sorry for the confusion. You just need to have a listener ready after initializing IAP. How you do that is totally up to you. And you need to handle scene changes too, something to keep in mind. Our Ads platform (and other services) are similar. One note, you need to explicitly unload listeners and hook them up again between scenes.
     
  16. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    My problem was, since I was reloading the scene, I had callbacks belonging to the old instance of the IAPService that I had defined. Reading your post what I did is to create a singleton and destroy new instances when created... now im thinking maybe my mistake was to put the Service in a monobehaviour
     
    JeffDUnity3D likes this.
  17. MattJackB

    MattJackB

    Joined:
    Oct 14, 2018
    Posts:
    37
    @JeffDUnity3D
    Hi there, I am currently trying to implement an IAP Listener to my scene.

    The IAP Listener component comes with a checkbox for the option "Don't Destroy On Load". When checked, however, if I change scenes and return to the original scene (containing the original IAP Listener), it creates a duplicate of the object that the IAP Listener is attached to.

    I was wondering how I can stop these duplicates from occurring, so that there is only ever one of this objects. Do I need to create my own script to destroy duplicates and then add this to the object containing the IAP Listener component? If so, why doesn't the IAP Listener handle this itself since it provides you with a checkbox for the "Don't Destroy On Load" option?
     
  18. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Do not use Codeless IAP, it hasn't been updated in some time and no immediate plans to do so. It will likely be eventually dropped. It's currently in place for users that may have used it in the past and need to upgrade in order to switch to Scripted IAP. I would recommend to start with scripted IAP with this Sample IAP Project v3 https://forum.unity.com/threads/sample-iap-project.529555/#post-7922275
     
  19. MattJackB

    MattJackB

    Joined:
    Oct 14, 2018
    Posts:
    37
    Oh snap, I had no idea! The documentation could do with being update to let people know that this is the case...

    Thanks for the help; luckily the project is in it's early days so I can try switching to scripted IAP:)

    EDIT:
    This is what I was using to implement IAP, along with various yt tutorials
    https://docs.unity3d.com/Manual/UnityIAPCodelessIAP.html
     
    Last edited: Sep 8, 2022