Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[Utility library - iOS] GKNativeExtensions - The missing iOS cloud save feature!

Discussion in 'Assets and Asset Store' started by Dark-1-Games, Mar 13, 2019.

  1. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Is it possible you have disabled iCloud on the device? Could you try with a different user maybe? I found this related issue:
    https://discuss.cocos2d-x.org/t/sdkbox-2-3-14-release-all-your-saves-on-the-cloud/37314/15
     
  2. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    385
    @Dark-1-Games Ah, I think that's because my iCloud is actually full :D
    I'll test when I get back to the project
    Thanks for help!
     
  3. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    Was it because it was full? I remember getting that error and that was not the reason.
     
  4. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    I'm sorry I use this thread to ask for help but since all of you are using the iCloud save game feature I think you might be able to help me:
    -I'm worried about the savefile's integrity, I mean, for the moment we are not keeping the player's progress in any other place than the player's iCloud, and, if for some reason, like an interruption during a save process, that save file would be corrupted, the player would lose his progress and we dont want that.
    I don't know if you know safety measures to avoid this, like maybe create always a copy of the file to overwrite and stuff like that for example. Any advice or hint is appreciated since im quite concerned about this.
    My save file consists on a text string which are serialized objects and dictionaries, right now im saving it as it is but I plan to compress the string inside (not the file) and also encrypt it.

    Also I have a doubt more related with GK, can players modify saved games in their iCloud space? I mean can they mess with the game save file if we are using GK ?

    Thanks a lot.
     
  5. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    I don't believe an interruption should cause any issues. In essence, the file is being saved on-device and then is synced using iCloud. Apps using iCloud use your space to save, but you cannot access them directly, so they should be tamper-safe.
     
  6. cyborgjinx

    cyborgjinx

    Joined:
    Dec 10, 2014
    Posts:
    28
    Did you ever find a solution? I’m having the same issue
     
  7. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    385
    @cyborgjinx You can go into build settings and disable bitcode for your actual game. That way, it will match the plugin, which was built without the full bitcode
     
  8. iB_Gaming

    iB_Gaming

    Joined:
    Apr 13, 2020
    Posts:
    10
    Hey guys has anyone successfully implemented the cloud save/load? I've been battling this for days and still cannot figure out what's wrong, but I can't seem to save my game data in the first place, so can't even test the loading methods. Do I perhaps need to configure the iCloud container in some specific way, like adding custom fields matching the variables I'm trying to save?

    Here's the code I'm using to try to save the game. CloudData is of type byte[], SaveData is a custom serializable class I'm packing with all the variables that need saving, just ints and bools and one datetime. Could someone please take a look and tell me if I'm doing anything wrong here? Or perhaps share their working code? I'd appreciate any help.

    Code (CSharp):
    1. public void SaveDataSave()
    2.     {
    3.         SerializeSaveData();
    4.         GKNativeExtensions.GKSaveGame(CloudData, "MyGameSaveData", (sdgccallback) => {
    5.             if (sdgccallback == null) Debug.Log("Error, failed to save data."); });
    6.     }
    7.  
    8. public void SerializeSaveData()
    9.     {
    10.         SaveData = new SaveData(/*variables to be saved*/);
    11.         using (MemoryStream ms = new MemoryStream())
    12.         {
    13.             xmlSerializer.Serialize(ms, SaveData);
    14.             CloudData = ms.GetBuffer();
    15.         }
    16.     }
     
  9. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Hi,
    Make sure to first authenticate the player to Game Center using Social.localUser.Authenticate, then call
    GKNativeExtensions.GKInit((conflicts) => {}). Calling these before trying to save / load is required.
     
  10. iB_Gaming

    iB_Gaming

    Joined:
    Apr 13, 2020
    Posts:
    10
    Hi, thanks for the reply and the library itself. Sorry it took me long, was investigating another idea why nothing works, to no avail, unfortunately.

    I do call those functions, in this way, to be precise:

    Code (CSharp):
    1. Social.localUser.Authenticate(success =>
    2.         {
    3.             if (success)
    4.             {
    5.                 LeaderboardLoad();
    6.                 GKNativeExtensions.GKInit((conflict) => {                  
    7.                     Debug.Log("GKInit conflict callback called.");
    8.                 }, (modified) => {
    9.                     Debug.Log("GKInit modified callback called.");
    10.                 });
    11.                 CheckForConflicts();
    12.             }
    13.             else
    14.             {
    15.                 Debug.Log("Apple authentification failed.");
    16.                 UIManager.Instance.ErrorDisplay(UIManager.ErrorType.SignIn);
    17.             }
    18.         });
    Do I need to adjust the iCloud container's schema in some specific way, maybe?
    Another thing is whenever I minimize and then reopen my app on device, judging by the console debug.logs, this function gets called again, does Awake() get called every time you reopen a minimized app on iOS?
     
  11. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Hi again,
    This is our setup:
    We have iCloud settings set like this in XCode:


    Then, in Certificates and Identifiers on the developer portal we have iCloud enabled like this on our app id:


    Finally, we have an iCloud container we have linked to the appId:


    I believe most of this configuration has been done automatically by XCode.
     
  12. iB_Gaming

    iB_Gaming

    Joined:
    Apr 13, 2020
    Posts:
    10
    Hey, I managed to get cloud saving to work a day or two ago, should have written here, my apologies.

    In case someone may find it uself, my two main mistakes were:

    1) I indeed didn't have iCloud documents enabled in xCode, as shown on the first screenshot above, as I only had the CloudKit enabled (that's how I interpreted the "requires an iCloud container" advice on GitHub).

    2) My save function was called in OnApplicationPause, and, from what I understand, the operation may take a few seconds, so saving couldn't be finished properly. Best have your saving functionality somewhere else.

    So, once again thanks to @Dark-1-Games for the replies and the library.
     
    Last edited: Oct 9, 2020
    Dark-1-Games and IgorAherne like this.
  13. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    Is there any way to know if the saving has synchronized with iCloud? I mean, does the operation ending successfully means the data is already on the iCloud servers? or that might take a while depending your connection and the data size?

    For example, lets imagine I have a document of 1MB, I call the save function, and save is succesful, but just after that I lose my connection or my battery dies.... How can I be sure the document has been successfully uploaded to iCloud? Is there any way to know it ? to know that the document is already on iCloud so will be downloaded for a second device (with the same iCloud account) ?

    I'm guessing this is not possible as I didn't see any similar function on the apple documents, although they don't offer too many info.

    Thanks for the asset!
     
  14. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Sorry, but that's not possible to do with the library. There might be ways to detect this by interfacing with the iCloud library directly, but it's more of an edge case, and apple probably didn't think it should be handled.
     
  15. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    Okay, thanks a lot for your fast answer.
    One more thing, if you are using 2 devices at the same time, with the same iCloud account, and both save on iCloud, what's the result? do you get a conflict notification? or some event triggers? I think I remember the asset we are using now (IOS Native Pro) has a couple of listeners for this case, but they never triggered when we tested this case.
    I'm asking this because the mentioned asset is dead, or at least it looks like, they dont answer to emails or forum post since April, and their last update doesn't even build.
    So we are preparing to probably change to this library.
    Thanks again.
     
  16. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Yes, there are listeners that get triggered and you can listen on them using the GKInit function. More specifically, both of the functions described here https://developer.apple.com/documentation/gamekit/gksavedgamelistener are implemented (hasConflictingSavedGames and didModifySavedGame). I remember I managed to get at least one of these callbacks called, and there was some delay (a few minutes)
     
  17. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    Hello again, I have a question about how the library works.
    Does it use for any chance NSMetadataQuery class and presentedItemDidChange() event?

    Found this in the apple developer forum:
    https://developer.apple.com/forums/thread/664089?page=1#643569022
    I dont exactly know how the API works inside but seems like there's an apple bug on iCloud among iOS 14 devices and others?
    They say queryDidReceiveNotification using NSMetadataQuery is not working anymore.
     
    Last edited: Oct 30, 2020
  18. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    We're not using that. You could look at the Objective-C source here - it's fairly simple and straightforward:
    https://github.com/dark-1-games/GKNativeExtensions/tree/master/GKNativeExtensions

    Cheers
     
  19. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    Finally trying to add your API but I'm getting the build error on Xcode:
    Code (CSharp):
    1. /Users/j...../Unity-iPhone.xcodeproj Building for iOS, but the linked library 'libGKNativeExtensions.a' was built for macOS.
    I tried removing the GKNativeExtnsionsMac bundle and trying to build again but I get the same.
     
  20. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    I'm not in front of my mac machine till monday, but if you have XCode you could build the library yourself, and just copy over the .a file.
     
  21. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    536
    Okay so I finally was able to add your library and test it but bad news is the same bug seems to be happening with this library.
    Saved games from iOS less than 14 won't be fetched in iOS 14 devices. No matter how you wait, no matter how many tries you attempt.
    Only way I could fetched the saved game was log out and login again from iCloud.

    This is quite worrying

    UPDATE: As expected, I tried with another device, this one a iPhone 6 with iOS 12.8. No problems synchronizing between iOS 13 ad 12. Seems to be an iOS 14 problem
     
    Last edited: Oct 31, 2020
  22. F5Foxie

    F5Foxie

    Joined:
    Jul 30, 2019
    Posts:
    6
    Hi pistoleta, I get the same error when trying to build my app in XCode.

    Did you resolve it like Dark 1-Games suggested by building the library in XCode?
    Is the XCode project here the one that I build to recreate the libGKNativeExtensions.a file?

    Thanks in advance :)
     
    pistoleta likes this.
  23. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Hey,
    I have made an error in my upload. Just updated the zip on the releases page with a new version.
    https://github.com/dark-1-games/GKNativeExtensions/releases/tag/0.3
     
    pistoleta likes this.
  24. F5Foxie

    F5Foxie

    Joined:
    Jul 30, 2019
    Posts:
    6
    Cool, thanks very much! Rebuilding using the XCode project did give me a version of the libGKNativeExtensions.a file that XCode was happy with, which I guess is what you've replaced it with as well.

    Thanks for updating the zip, will definitely help newcomers.

    I think I'm close to having it working, just missing something on the iCloud setup side of things. When I call methods to load save games or save the game, I see this message logged on the device:

    "The requested operation could not be completed because you are not signed in to iCloud or have not enabled iCloud drive"

    I have enabled iCloud in the settings on the phone and am signed in on the device. The Game Center and iCloud capabilities have been added in XCode as well, with all options ticked.

    On App Store Connect I have Game Center ticked for the new unreleased version of the game, and do not see anything for iCloud or cloud save under Features that I can set up as well.

    I think I still need to set up an iCloud Container for the app, but otherwise any ideas on what else I should check would be greatly appreciated!

    Thank you very much for the GKNativeExtensions asset as well, seems to be just what I need to interface to GK Save games in Unity.
     
  25. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello,

    First off, thank you for making this code available. I really appreciate you sharing it with the community like this.

    I am a bit confused how to use GKInit and GKFetchSavedGames together.

    I understand that the system can be slow to respond with conflicts. I also understand there is a platform issue with calls not responding right after a new install.

    Those issues asside, how am I supposed to design my flow?

    I call GKInit first.

    If there are conflicts, great, I get the callback. I handle the resolution, and I move forward.

    How do I know there are no conflicts though? It seems like I don't have a notify for that.

    So, am I supposed to call GKFetchSavedGames immediately after calling GKinit?

    I get my GKFetchSavedGames result, process the save data, and move on.

    Then, some point down the road, possibly after the player has already started playing, I have to be prepared to maybe receive a GKInit conflicts detected callback?

    Am I missing something?

    Thank you for your time
     
  26. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Under the hood, GKInit only subscribes to the GKSavedGameListener protocol:
    GKSavedGameListener | Apple Developer Documentation

    It's not really clear from the documentation when exactly a conflict is detected, but from my tests it was happening whenever two devices save a game with the same id while one of the devices is offline, and then regains connection. Only one of the two devices gets the conflict callback, and this can happen at a random time. It's not required to immediately resolve the conflict though, you can wait until it's appropriate in your game.

    It's a good idea to do a few little experiments and simulate some of these cases, as things do change over time and different iOS versions.
     
  27. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello @Dark-1-Games,

    Thank you for the speedy response. I appreciate it.

    Sounds like GKInit is just setting those callback params aside for when other GK methods need to use them? GKInit isn't actually doing any load or conflict detection of it's own?

    And so, I should just call GKFetchSavedGames immediately after GKInit?

    Sorry if I am not making my question understood very well.

    Again, thank you for your time on this project.
     
  28. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Yes, GKInit only initializes the listeners:
    GKNativeExtensions/GKNativeExtensions.mm at master · dark-1-games/GKNativeExtensions (github.com)
    So you should call GKFetchSavedGames immediately after.
     
  29. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello again @Dark-1-Games

    Thank you for that clarification.

    Unfortunately, I can't seem to get this working.

    When I call fetchSavedGames, I get the following error:

    "The requested operation could not be completed because you are not signed in to iCloud or have not enabled iCloud Drive".

    However, both of those things are true for my test device.

    This is happening when I build and deploy from xCode.

    So, I thought maybe iCloud won't work unless I deploy to TestFlight and download a build from there.

    However, that also doesn't work. I am unable to get logs from the TestFlight build though; so I don't exactly know what is wrong in that situation.

    Have you encountered this error before? How do you normally debug / test this flow?

    Once again, thank you for your time and your assistance. I really appreciate you making this available and supporting it.

    Cheers

    Edit: I should have mentioned, but I already tried the standard responses for googling that error message: Confirmed my devices iCloud log in status. And tried resetting all settings (related to iOS7 versions).
     
    Last edited: May 25, 2021
  30. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    I've seen that before, for me it was usually a misconfigured iCloud setup. The library requires you to set up an iCloud container:
    https://developer.apple.com/account/resources/identifiers/list/cloudContainer

    And connect that container up in the Certificates, identifiers & profiles page:

     
  31. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Thank you, once again, @Dark-1-Games for your help.

    I had already added my containers via xCode.

    However, under the "Select the iCloud you wish to assign to the bundle." section, my app erroneously had 2 items selected. I fixed that and made new builds. Unfortunately, I am getting the same result.

    Off topic, but can this only be tested in builds that come from TestFlight? Or can I test builds made in xCode directly onto my test device? (For now, I have been testing from TestFlight.)

    Thank you again
     
  32. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    I don't remember such a thing being an issue, I think I didn't have any issues running directly from XCode.
    Unfortunately I haven't been using the library lately due to current projects not requiring it, so I don't think there's too much I can help you with.

    We do have a discord channel with other devs that have used it successfully, maybe some of them know more, feel free to join:
    http://discord.gg/vtXgXGU

    Here's one other thing to check that some people had issues with, the entitlements file:
    It should look something like this:

    Code (XML):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd%22%3E
    3. <plist version="1.0">
    4.   <dict>
    5.     <key>com.apple.developer.icloud-container-identifiers</key>
    6.     <array>
    7.       <string>iCloud.com.yourstudio.game</string>
    8.     </array>
    9.     <key>com.apple.developer.icloud-services</key>
    10.     <array>
    11.       <string>CloudDocuments</string>
    12.     </array>
    13.     <key>com.apple.developer.ubiquity-container-identifiers</key>
    14.     <array>
    15.       <string>iCloud.com.yourstudio.game</string>
    16.     </array>
    17.   </dict>
    18. </plist>
     
  33. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello @Dark-1-Games ,

    I just figured out what my problem was.

    In xCode, when adding the entitlements, I had checked 'CloudKit' instead of 'iCloud Documents'. I didn't realize what this was, and just checked the wrong thing ><.

    Also, I can confirm that you do not need to deploy builds through TestFlight in order to test iCloud. iCloud works in builds directly from xCode to device.

    Thank you for you continued support and assistance with this. Do you have any sort of patreon or other way for me to contribute to your endeavors?
     
  34. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Glad to hear it works for you!
    If you want to support us, just buy our games on steam :D
     
  35. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Deal! Odium To The Core looks pretty sweet. I'll give it a shot tonight.

    Cheers for all your help with this project
     
  36. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello again @Dark-1-Games,

    How do I detect the scenario where the user has disabled iCloud on their device?

    I get an error code when trying to do a read or write, but I would like to check the status before initiating these calls.

    Do you know how to do this?

    Thank you
     
  37. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Does anyone know how to add error handling to this code?

    The unity project appears to be some sort of c# wrapper around apple's objective c code. I am not very familiar with this setup.

    The reason I ask is because I am trying to catch the following use case:

    1) User has iCloud disabled
    2) My code calls GKInit (no issues detected)
    3) My code calls GKFetchSavedGames
    4) xCode displays an error output message "The requested operation could not be completed because you are not signed in to iCloud or have not enabled iCloud drive"
    5) GKNativeExtensions silently calls back into my code without any issue

    This makes it look like a new save is being created within iCloud.

    I need to somehow capture and detect that error message.

    Some searching suggests that it's Error Domain=GKErrorDomain Code=27 being triggered by the apple code. However, the GKNativeExtensions doesn't seem to have error handling.

    This is the actual apple signature for fetchSavedGames. You can see it provides an error code.
    https://developer.apple.com/documentation/gamekit/gklocalplayer/1521086-fetchsavedgames

    So, does anyone know how I can adapt this c# wrapper to support this?

    Thank you
     
    Last edited: Sep 29, 2021
  38. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    So the part that does this error handling that you mention is here:
    GKNativeExtensions/GKNativeExtensions.mm at master · dark-1-games/GKNativeExtensions (github.com)

    It calls the callback with null as the value of the saved game data (which means there was an error and no data has been returned). If you want more details on the C# part on why this fails, you could maybe add another parameter to the callback, perhaps an errorCode, or a struct that is contains more data from the error.
     
  39. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello @Dark-1-Games ,

    Thank you for that information.

    Does that mean the following is true for the C# side of things?

    1) A brand new setup will return a zero length, non null, array of saved game data
    and
    2) Errors will return a null value for the array of saved game data

    If that is the case, then it seems like I can differentiate between things after all.

    Thank you again
     
  40. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Yes, that sounds right.
     
  41. Archi_16

    Archi_16

    Joined:
    Apr 7, 2017
    Posts:
    84
    Hello. Do I need to wait for Init, before calling Save,Load or FetchSave?
    If so, how?
    I have added on more callback on _GKInit(..., ..., Action OnDone) and invoking it at the end, just after the
    isInited = true.
    On that action I'm doing the other things, fetching and loading. But it seems sometime it didn't work. it is kind of not seeing any saves, and don't loads it from cloud.
    Thanks.

    [UPDATE] The main problem is that on very 1st run of the game/application, fetching returns 0 saved games. After that on every game opening everything works great.

    [UPDATE 2] Data is fetching, without initing. but it takes some time. is there any event to hook and know when data gathered.
     
    Last edited: Dec 16, 2021
  42. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    This is a common issue, but unfortunately the GKSavedGame API does not expose any such hook. The only solution is to just retry, and after some time let the user decide if they want to keep trying or not.

    I have reported this issue to apple back in 2019, and according to the report, it should have been solved in iOS 13, but I haven't had the opportunity to deep dive and see if there are any changes.

     
  43. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello again @Dark-1-Games

    I have been using this code in my live game, and some players are encountering errors when trying to load from iCloud.

    This sent me digging through my code again; trying to figure out where my bug is.

    This is a flow chart for my iCloud load code. As you can see, I have 2 spots that appear suspect.

    1) I don't do anything if my onInitModified callback is called. My code just halts. Obviously this is wrong, but it's unclear to me what I should be done and what this method is representing.

    2) I thought I was doing my conflict resolution properly. I just choose 1 of the saves and load it. However, sifting through your GKNativeExtensions code revealed the GKResolveConflicts method. I am not calling this. Am I supposed to? How should it be used? Do I insert it, wait for the callback, and then load? I'm confused why it takes in an array of saves as well. How do I specify which of the saves to keep?
    i cloud load flow chart.jpg

    Thank you again for you help with this project.
    Les

    PS Dark-1's game, Odium To The Core, is quite fun. For anyone else coming here; you should check it out on steam.
     
  44. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Has anyone figured out how to use GKResolveConflicts?

    I am currently trying the following:
    - GKInit(OnConflicts, OnModified)
    - My OnConflicts gets called
    - I am passed an array with 2 saves (parameter named conflictingSaves)
    - I pick the newest of those saves
    - I call GKLoadGame(OnLoadDone) with the chosen, newest save
    - My OnLoadDone gets called
    - I am passed the byte[] data for that loaded game save
    - I then call GKResolveConflicts with the original array of conflicting game saves (conflictingSaves) and the byte[] data that I just got from loading that chosen, newest save option

    However, this fails. I get the following output

    The requested operations could not be completed because one or more parameters are invalid.

    Any help would be apreciated.
    Thank you
     
  45. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    Sorry for the delayed response.
    Could you try calling simplifying this and calling GKResolveConflicts without first loading your game? Then when GKResolveConflicts completes, call GKLoadGame.
    I haven't encountered this issue before. How big is your save data? Could you try saving and loading something smaller, perhaps in a small repro project?
     
  46. LesBloom

    LesBloom

    Joined:
    Feb 2, 2017
    Posts:
    163
    Hello @Dark-1-Games

    "Could you try calling simplifying this and calling GKResolveConflicts without first loading your game?"

    What is the byte[] param that I am supposed to pass to GKResolveConflicts?

    I assumed that the byte[] is the actual data that should be saved into the new, single save. How am I supposed to know what that data is without first loading a file?

    Maybe that is where I am getting confused.

    Thank you
     
    Last edited: Mar 30, 2022
  47. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    In the onConflicts callback, you are able to load both of the conflicting games you get as the first parameter.
     
  48. wwidelec1

    wwidelec1

    Joined:
    Dec 9, 2017
    Posts:
    6
    Hello,
    I have this error after build:

    Code (CSharp):
    1. ld: bitcode bundle could not be generated because '/Users/makus/Desktop/Ced_/Libraries/GKNativeExtensions/Plugins/IOS/libGKNativeExtensions.a(GKNativePlayerListener.o)' was built without full bitcode. All object files and libraries for bitcode must be generated from Xcode Archive or Install build file '/Users/makus/Desktop/Ced_/Libraries/GKNativeExtensions/Plugins/IOS/libGKNativeExtensions.a' for architecture arm64
    2. clang: error: linker command failed with exit code 1 (use -v to see invocation)
    I saw your answer to this "You can build from source with whichever options you want, just open up the GKNativeExtensions Xcode project and you're good to build." But i still don't understand what should I do.

    Thanks in advance!
     
  49. Dark-1-Games

    Dark-1-Games

    Joined:
    Mar 26, 2014
    Posts:
    99
    The easiest thing to do is to just copy over all .mm and .h files into Assets/Plugins/iOS in your project (Create this if it doesn't exist). These filles are located here
     
    KyryloKuzyk likes this.
  50. KyryloKuzyk

    KyryloKuzyk

    Joined:
    Nov 4, 2013
    Posts:
    1,070
    Hi, @Dark-1-Games

    Huge thanks for building this library! I used Stans Assets implementation in the past, but they abandoned their product, so I decided to move to something else.

    I implemented the GKNativeExtensions and everything was fine for simple cases. Unfortunately, when I decided to test conflict resolution, it started crashing.

    The crash is happening after the call to GKNativeExtensions.GKFetchSavedGames. Saved games are being downloaded, I can see the conflicting saves games, but immediately after receiving the callback, by app crashes. I tested this in a fresh project with no other dependencies.

    The crash is coming from "UnityAppController(Rendering) processTouchEvents crash", which is not helpful. I tried to pinpoint the exact crash place, and my best guess is that it crases after calling this callback. Maybe the issue lies in native-to-managed memory management.

    It worked OK when I had these saved game files:
    - SAVE1, iPad
    - SAVE2, iPad

    But when I created a conflict for SAVE1 it started to crash:
    - SAVE1, iPad
    - SAVE1, iPhone
    - SAVE2, iPad

    My setup:
    Unity 2021.3.4f1
    iPad Pro 2020 iOS 14.5.1
    iPhone 13 Pro iOS 15.5
    Xcode 13.3
    I didn't use the pre-compiled libraries. Instead, I used the source code files directly.

    Unfortunately, I don't have time to investigate further, Google Saved Games/Apple GKSavedGame were always a huge pain to implement. It's an overkill for simple games and I believe I'll just remove them from my game. Or will replace them with the key/value solution from CloudOnce as their solution never failed me before in another project.

    Nevertheless, huge thanks for developing the GKNativeExtensions and releasing it to the public! I hope my information will be helpful.
     
    Last edited: Jun 23, 2022