Search Unity

Question Integrating with a simple RPG system

Discussion in 'Game Foundation' started by BeorGames, Mar 21, 2021.

  1. BeorGames

    BeorGames

    Joined:
    Jul 28, 2018
    Posts:
    65
    Hello! I've been poking around with the Game Foundation for around a day now and haven't understood how to integrate anything with my game yet o_O

    I've followed the documentation and managed to create the daily reward system, some rewards and a currency for the game, now I want to use it inside the game and the first problem I get is that the reward system is not saving, any new session I can get again the first day reward and it will not move to the second day.

    I've downloaded the Sample 06 Data Persistence, created a new script with what I believe is necessary from the DataPersistenceSample (File attached), and it's still not saving. In my game I use a fairly simple save system:

    Code (CSharp):
    1. SavedGame[] savedGames = new SavedGame[3];  
    2.  
    3.         BinaryFormatter formatter = new BinaryFormatter();
    4.  
    5.         string path = Application.persistentDataPath + "/save" + saveSlot + ".save";  
    6.  
    7.         FileStream stream = new FileStream(path, FileMode.Create);
    8.  
    9.         savedGames[saveSlot] = new SavedGame();
    10.  
    11.         formatter.Serialize(stream, savedGames[saveSlot]);
    12.  
    13.         stream.Close();
    I've added this at the end of my save system:
    Code (CSharp):
    1. UnityEngine.GameFoundation.RewardsSave.instance.Save();
    I need that each one of the three slots the player can play is independent regarding the daily rewards and that it saves in the same file as all the rest of the game, is there a tutorial for that?

    P.S. I already have a currency system working on the game and I will not use the Game Foundation currency system yet, I need to integrate that the reward is given in my other system, but I haven't started looking for it yet, since the save isn't working.
     

    Attached Files:

  2. erika_d

    erika_d

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hi @BeorGames,

    I tested your RewardsSave script that you attached using the Rewards Sample Scene (which can be found by going to Window -> Game Foundation -> Import Prefabs and Samples) and it did work for us. You can test with that sample scene like we did by attaching it to a game object in that scene, adding a button for saving the state, and changing the Game Foundation Init component (attached to the game object called Game Foundation) to Local Persistence instead of Memory. I'd also suggest that the safest way of ensuring reward claims are saved would be to trigger a save each time a reward is claimed (you may already be doing this, I'm just throwing it out there).

    One theory I have for why it might look like it's not working for you is if you're initializing Game Foundation using the memory data layer, instead of the Local Persistence one. You can adjust that in the data layer drop down of the Game Foundation Init component, if you're using that.

    Another theory I have is that perhaps your Reward is configured as Reset If Expired = true in the Reward window, and then the cooldown and expiration period passes before you reload that save file. This would make it look like it's never progressing past the first reward (cause it does progress, but then once it expires it goes back to the beginning). This was something that threw me off at first when I was testing your script as well.

    For example in the below configuration, if I claim the first item in the Reward, save the file, then stop and restart the game, if the time between when I claimed the first Reward item and when I relook at the reward is more than one minute and 30 seconds, it will have reset the reward and will show me the first item as the one that's available to claim again.

    Screen Shot 2021-03-22 at 5.32.20 PM.png

    I'm also not sure whether you want to keep your class in the Game Foundation namespace, whether that could cause any problems for it down the line or anything.

    If you've confirmed that your GameFoundationInit is set to LocalPersistence data type instead of Memory data type, have tried testing with Reset If Expired = false or changing the namespace and saving still doesn't work for you then I would need to see your Reward configuration, and maybe more of your code (when you trigger your save method for example) to troubleshoot further.

    Here are some thoughts regarding your other three questions:

    - For slots for three different players, you would need to set that up by using three different save files, at this time, Game Foundation doesn't support different player ids in a single local persistence save file.

    - For being able to save Game Foundation data in the same file as the rest of your game's save data. Game Foundation isn't set up to do this right now, I can raise it as a possible request. But for now, you might be able to hack together something where you write your data to the same file that Game Foundation uses, but I would be concerned about your other save data accidentally getting overwritten by Game Foundation, if for example you don't have all your data saved outside the file when you pass it to Game Foundation to save its info, or Game Foundation not being able to parse the file, if there's unexpected data in it. In general I would recommend keeping the two pools of data in separate files if at all possible.

    - For getting Rewards to work with your currency system. We don't have a way of having the Rewards system payout something that is not a Game Foundation currency or inventory item, so what I would suggest doing to get it to work with your existing currency system is to create the currencies you need in the Game Foundation window and set them as the payouts for your reward. Then listen to the GameFoundationSdk.wallet.balanceChanged event, when that gets triggered you can find out which currency and what amount our wallet system changed, and then make that change in your system.

    Hope all that information helps! Let us know if you still have trouble getting your rewards to save after trying those things!
     
    BeorGames likes this.
  3. BeorGames

    BeorGames

    Joined:
    Jul 28, 2018
    Posts:
    65

    Hello Erika!

    First of all, thanks for your really complete answer!!! Never received such complete answer from any forum!
    Second, it's really nice to learn from you on the video tutorial and than receive an answer from you here in the forums, made a really personal experience! Thanks for that! (if you're not a bot ;))

    It works!!!
    So, I've managed to create three instances of the GameFoundationInit and three instances of the ProgressRewardPopup, and I activate it based on the loaded slot so I'm good to go with three different save files.

    So far so good, already drank a glass of wine to celebrate the save system working!
    The following part regards new problems, let me know if we should close this thread and open a new one.

    Now comes the problems:

    I can't work with the GameFoundationSdk.wallet.balanceChanged event, maybe I'm too noob, but I've added to my CoingBag script the following lines at the start method:
    Code (CSharp):
    1. UnityEngine.GameFoundation.GameFoundationSdk.wallet.balanceChanged += GetFoundationBallance;
    And written this simple code to update my ballance:

    Code (CSharp):
    1. public void GetFoundationBallance(UnityEngine.GameFoundation.IQuantifiable currency, long value)
    2.     {
    3.         Debug.Log("Calling foundation ballance");
    4.         if (currency.quantity > foundationMoney)
    5.         {
    6.             AddCoins((int)currency.quantity - (int)foundationMoney);
    7.         }
    8.         else if (currency.quantity < foundationMoney)
    9.         {
    10.             RemoveCoins((int)foundationMoney - (int)currency.quantity);
    11.         }
    12.         foundationMoney = currency.quantity;
    13.     }
    But it's not calling the event! The debug log is there to prove it, and my coin bag isn't updating as expected, what have I done wrong?

    After this main problem, I'm getting an error in the editor:

    Code (CSharp):
    1. InvalidOperationException: Destroying a GameObject inside a Prefab instance is not allowed.
    2. UnityEngine.Object.DestroyImmediate (UnityEngine.Object obj) (at <fe84f4a754da4a6bb64fca409d40938a>:0)
    3. UnityEngine.GameFoundation.Components.RewardPopupView.ClearRewardItemPrefabs () (at Library/PackageCache/com.unity.game-foundation@0.8.0-preview/Components/Runtime/RewardPopupView.cs:1128)
    4. UnityEngine.GameFoundation.Components.RewardPopupView.UpdateGeneratedRewardItemsAtEditor (UnityEngine.GameFoundation.DefaultCatalog.RewardAsset rewardAsset) (at Library/PackageCache/com.unity.game-foundation@0.8.0-preview/Components/Runtime/RewardPopupView.cs:1083)
    5. UnityEngine.GameFoundation.Components.RewardPopupView.UpdateContentAtEditor () (at Library/PackageCache/com.unity.game-foundation@0.8.0-preview/Components/Runtime/RewardPopupView.cs:1068)
    6. UnityEngine.GameFoundation.Components.RewardPopupView.UpdateContent () (at Library/PackageCache/com.unity.game-foundation@0.8.0-preview/Components/Runtime/RewardPopupView.cs:914)
    7. UnityEditor.GameFoundation.Components.RewardPopupViewEditor.OnEnable () (at Library/PackageCache/com.unity.game-foundation@0.8.0-preview/Components/Editor/RewardPopupViewEditor.cs:119)
    Don't really know what it is about, but I only get it when I exit play mode, so it's not bugging my gameplay.

    And last but not least, I want to expand this system to work with items as well, how can I add this event listener to a prefab?

    Thanks!
     
    erika_d likes this.
  4. erika_d

    erika_d

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hello @BeorGames!

    Yay that you got it working! I'm glad the answer (and the video tutorial) were helpful, and yes I am 100% bot-free :D

    I'm a bit concerned with the idea of using 3 GameFoundationInit instances to do the 3 slots...there's only supposed to be one in any given scene, and they have code in them that will delete any others that happen to be there, so I worry that you may not end up with the one you intended on the scene, or that one that you don't think is active might still be or something like that. So I would say proceed with caution there, and if you run into bugs (like this listener not getting triggered) test with only one in the scene to make sure it's not that causing the problem.

    Instead of doing 3 different GameFoundationInit instances, I would suggest keeping string values for the 3 save files you want to use, then when you want to change save files, uninitializing Game Foundation, change the save file set on the single GameFoundationInit instance, then re-initialize. (I actually don't know whether uninitializing first is necessary, but I think it would be safer)

    From the code you shared, I'm not sure why the callback wouldn't be being triggered, other than perhaps a race condition with the GameFoundationInits. You could try adding a CurrencyHUD prefab to your scene and connecting it to the currency you have set up in Game Foundation, that way you can determine whether the reward is properly dispersing the Game Foundation currency or not (if it's not that could indicate something set up incorrectly on the reward, if it is then something wrong with the connection to the callback). Let me know how those tests go!

    The other error about destroying a game object is something we've seen before, although we thought we had caught all the ways it could happen. When you look at your prefab in prefab edit mode (vs in your scene or at runtime) does it show reward items being added inside the AutoPop Reward Items Container or is that game object empty? If you want to send a screenshot of your reward configuration in prefab edit mode I might be able to help get that error to go away. We've also been working on some changes lately to try and make the prefabs more resistant to triggering that error.
     
  5. BeorGames

    BeorGames

    Joined:
    Jul 28, 2018
    Posts:
    65
    We did it! Thank you so much! :D

    The last considerations:
    Indeed it wasn't working with the three GameFoundationInits, even if they were child of another game object and were activated by demand, I had to work with only one.
    I was avoiding changing the name of the save file because GameFoundationInit.localPersistenceFilename is "read only" and I couldn't find a way to set or to change it, so I actually changed the GameFoundationInit.m_LocalPersistenceFilename to public and than I could change it's value, even though it is really annoying editing anything in the GameFoundationInit because it self restore to it's default state depending on the changes on the file, don't know how or why it does it...:eek:

    Another thing that was causing the error was that I was trying to uninitialize and initialize the GameFoundationInit in the Progressive Reward Popup.onPopupOpened, but it wasn't called, tried to Debug.Log it and it was never called, I created a new button to do it while activating the Reward Popup as well.

    About the destroying error, the Reward Popup in the editor shows only part of the rewards, here's a SS reward editor.png
    Instead during runtime it shows all rewards: reward runtime.png

    Thanks again, now it's time to find a way to work with items, if I run into any trouble I'll open a new post ;)
     
    erika_d likes this.
  6. erika_d

    erika_d

    Joined:
    Jan 20, 2016
    Posts:
    413
    Hi @BeorGames

    Great, glad to hear its working now! Not being able to set localPersistenceFilename from code sounds like an oversight on our part, I've created a ticket to look into it and confirm that that wasn't intentional protection against any bugs.

    All the files in our package are readonly, just by nature of it being in an imported package, I believe. I would suggest copying our component's code into your own class that you can then edit and save how you like.

    The onPopupOpened event gets triggered whenever the Open() or Open(Reward) methods get called. I'm not sure why it wasn't triggering for you, I just tested and it worked for me. You can send the code you're using to open the reward and subscribe to the event if it's still not working for you. That being said, I don't think that's the place that you would want to reinitialize GameFoundation, as that event gets triggered after the reward to display has been fetched from Game Foundation and the popup has been set to active. So doing it in the button that triggers the opening is probably the right place to make that change. (Although keep in mind initializing Game Foundation is technically asynchronous, and though it's generally instantaneous when just using a local data layer, there's no guarantee that it will be, so that could cause a long delay between when the open reward button is clicked, and when the popup actually shows up in some cases. Ideally the user would already have picked which save file to use before the reward is offered for viewing.

    That's weird that the Reward in the editor doesn't show all the possible rewards, I can't think of why that would be (that looks like it's not the screenshot from prefab edit mode though so I don't think that solves the destroying error, but still weird). If you want to send more info about your reward setup we can look into why it might be doing that.
     
    BeorGames likes this.
  7. BeorGames

    BeorGames

    Joined:
    Jul 28, 2018
    Posts:
    65
    Hello!

    For the onPopupOpened event, I was actually activating the Popup using a button with the GameObject linked to it and using the SetActive(True) on the button, never called it on a script. Now I'm still activating it on the same way, I'll keep in mind about the asynchronous initialization if I run into any weirdness.

    About the reward in the editor, I've closed the editor and reopened it started working just fine.

    Now about the reward setup, for both coins and items I'm using only the methods to add the rewards and not accounting the coins and items already in the wallet/inventory.

    For coins:

    Code (CSharp):
    1.     public void SubscribeToGameFoundation()
    2.     {
    3.         UnityEngine.GameFoundation.GameFoundationSdk.wallet.balanceChanged += GetFoundationBallance;
    4.     }
    5.  
    6.     public void GetFoundationBallance(UnityEngine.GameFoundation.IQuantifiable currency, long value)
    7.     {
    8.         AddCoins((int)value);
    9.     }
    10.  
    11.     public void AddCoins(int amount)
    12.     {
    13.         //Animate(amount, true);
    14.         InstantiatePopUp(amount);
    15.         coins += amount;
    16.         UpdateMoneyBag();
    17.         audioManager.Play("Coins");
    18.     }
    For items
    Code (CSharp):
    1.     public void SubscribeToGameFoundation()
    2.     {
    3.         UnityEngine.GameFoundation.GameFoundationSdk.inventory.itemAdded += GetFoundationItem;
    4.     }
    5.  
    6.  
    7.     public void GetFoundationItem(UnityEngine.GameFoundation.InventoryItem item)
    8.     {
    9.         Item i = item.GetDefaultValueOfMutableProperty("object").AsAsset<Item>();
    10.         if (Add(i))
    11.             return;
    12.         else
    13.             itemOnHold = i;
    14.     }
    Everything is working already, now I'm just trying to figure out why the icons are resizing like crazy icons.png :p but I'm pretty sure I can find why
     
  8. erika_d

    erika_d

    Joined:
    Jan 20, 2016
    Posts:
    413
    Glad everything seems like its working smoothly now!

    For this part:
    Just to clarify when you say it started working fine, is it that you're not getting the destroying error anymore or is it that all the rewards that should be showing up are showing up in both edit and runtime mode? Or both?

    For the icons, I think likely what is happening is that in the 0.8 release our icons were set to show in the icons native size, so it would display just how the icon was designed. To get the icons to display the size you want them to show up as you need to provide icons that are the exact size (i.e. scale them down in photoshop or some such tool and then add that new image to the static properties of the items in the Game Foundation window). Our current codebase has changed it from setting the native size to preserving the aspect while shrinking or expanding the icon to fill the space, but I don't have a date on when that change will be released.
     
  9. BeorGames

    BeorGames

    Joined:
    Jul 28, 2018
    Posts:
    65
    Hi Erika,

    About this:

    It actually started showing all the icons, I'm still getting the error.

    And about the icon sizes, for now I've added a Grid Layout Group, even tough it's expansive, the rewards window should be opened only once per session, it shouldn't impact that much.
     
    erika_d likes this.