GKLocalPlayer.Local.FetchItems() appears to get stuck

Hello,

We’re trying to properly set up Game Center authentication in our project. I’ve followed the instructions outlined here: Apple Game Center

In the first Login() function from the above link, var player = await GKLocalPlayer.Authenticate(); finishes successfully, and we can get the local player’s display name. However, immediately following that line of code, we have:

var fetchItemsResponse = await GKLocalPlayer.Local.FetchItems();
Signature = Convert.ToBase64String(fetchItemsResponse.GetSignature());
TeamPlayerID = localPlayer.TeamPlayerId;
Debug.Log($"Team Player ID: {TeamPlayerID}");

and we never receive that debug log, as it appears we are stuck waiting for FetchItems(). At this point, we receive the following warnings from Xcode:

Failed to load cached image from gamed: monogram-256@2x~iphone.gkpix

cache key: avatars__U:a589827e7e51ddeb1aa4da6c29cc87eb_18308696552540808511monogram-256@2x~iphone.gkpix

and then the following warning triggers repeatedly until we close the application:

nw_connection_copy_connected_local_endpoint_block_invoke [C3] Connection has no local endpoint

We’re having trouble understanding what the warnings mean. Is anybody able to help us out?

Thanks!

1 Like

I’m experiencing a crash in the same location — just doing some reading around it appears as if the Game Center implementation for Unity has several issues that people are running into relatively recently?

Sorry I couldn’t be any assistance, I’ll let you know if I get past this point.

Uploading Crash Report
MissingMethodException: Default constructor not found for type Apple.Core.Runtime.NSData
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00000] in <00000000000000000000000000000000>:0
  at Apple.Core.Runtime.ReflectionUtility.CreateInstanceOrDefault (System.Type type, System.IntPtr pointer) [0x00000] in <00000000000000000000000000000000>:0
  at Apple.Core.Runtime.ReflectionUtility.CreateInstanceOrDefault[T] (System.IntPtr pointer) [0x00000] in <00000000000000000000000000000000>:0
  at Apple.GameKit.GKLocalPlayer.OnFetchItems (System.Int64 taskId, System.String publicKeyUrl, System.IntPtr signaturePtr, System.IntPtr saltPtr, System.UInt64 timestamp) [0x00000] in <00000000000000000000000000000000>:0
--- End of stack trace from previous location where exception was thrown ---

  at GameCenterManager.Login () [0x00000] in <00000000000000000000000000000000>:0
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <00000000000000000000000000000000>:0
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run () [0x00000] in <00000000000000000000000000000000>:0
  at System.Threading.Tasks.AwaitTaskContinuation.RunCallback (System.Threading.ContextCallback callback, System.Object state, System.Threading.Tasks.Task& currentTask) [0x00000] in <00000000000000000000000000000000>:0
  at System.Threading.Tasks.Task.FinishContinuations () [0x00000] in <00000000000000000000000000000000>:0
  at System.Threading.Tasks.Task.TrySetException (System.Object exceptionObject) [0x00000] in <00000000000000000000000000000000>:0
  at System.Threading.Tasks.TaskCompletionSource`1[TResult].TrySetException (System.Exception exception) [0x00000] in <00000000000000000000000000000000>:0
  at Apple.Core.Runtime.InteropTasks.TrySetExceptionAndRemove[TResult] (System.Int64 callbackId, System.Exception exception) [0x00000] in <00000000000000000000000000000000>:0
--- End of stack trace from previous location where exception was thrown ---

Hi!

Facing with the same issue in the same place.
Did you find any workaround?

Same issue here can’t get it to work…

The problem is NSData share class is not implement default constructor.
Maybe that is a bug form Apple Plugin Unity team.
We can fixed it plugin source and rebuild it.
Here is my fixed for it:

// File NSData.cs (Apple.Core_Unity/Assets/Apple.Core/Runtime)

using System;
using System.Runtime.InteropServices;

namespace Apple.Core.Runtime
{
    /// <summary>
    /// C# wrapper around NSData.
    /// </summary>
    public class NSData : NSObject
    {
        /// <summary>
        /// Construct an NSData wrapper around an existing instance.
        /// </summary>
        /// <param name="pointer"></param>
        public NSData(IntPtr pointer) : base(pointer)
        {
        }

        /// <summary>
        /// Default constructor that initializes an empty NSData instance.
        /// </summary>
        public NSData() : base(CreateEmptyNSData())
        {
        }

        /// <summary>
        /// The number of bytes contained by the data object.
        /// </summary>
        public UInt64 Length => Interop.NSData_GetLength(Pointer, NSException.ThrowOnExceptionCallback);

        /// <summary>
        /// Return the object's contents as a byte array.
        /// </summary>
        public byte[] Bytes
        {
            get
            {
                byte[] bytes = null;

                var length = (int)Length;
                var bytePtr = Interop.NSData_GetBytes(Pointer, NSException.ThrowOnExceptionCallback);
                if (length >= 0 && bytePtr != IntPtr.Zero)
                {
                    bytes = new byte[length];
                    Marshal.Copy(bytePtr, bytes, 0, length);
                }

                return bytes;
            }
        }

        /// <summary>
        /// Creates an empty NSData instance using a native method.
        /// </summary>
        /// <returns>Pointer to the newly created empty NSData object.</returns>
        private static IntPtr CreateEmptyNSData()
        {
            // Replace this with the actual method to create an empty NSData object
            return Interop.NSData_CreateEmpty(NSException.ThrowOnExceptionCallback);
        }

        private static class Interop
        {
            [DllImport(InteropUtility.DLLName)] public static extern UInt64 NSData_GetLength(IntPtr nsDataPtr, NSExceptionCallback onException);
            [DllImport(InteropUtility.DLLName)] public static extern IntPtr NSData_GetBytes(IntPtr nsDataPtr, NSExceptionCallback onException);

            [DllImport(InteropUtility.DLLName)] public static extern IntPtr NSData_CreateEmpty(NSExceptionCallback onException);
        }
    }
}

// NSData.m (Apple.Core/Native/AppleCoreNative)

//
//  NSData.m
//  AppleCoreNative
//

#import <Foundation/Foundation.h>

NSUInteger NSData_GetLength(void * nsDataPtr, void (* exceptionCallback)(void * nsExceptionPtr)) {
    @try {
        if (nsDataPtr != NULL) {
            NSData * nsData = (__bridge NSData *)nsDataPtr;
            return nsData.length;
        }
    }
    @catch (NSException * e) {
        exceptionCallback((void *)CFBridgingRetain(e));
    }
    return 0;
}

const void * NSData_GetBytes(void * nsDataPtr, void (* exceptionCallback)(void * nsExceptionPtr)) {
    @try {
        if (nsDataPtr != NULL) {
            NSData * nsData = (__bridge NSData *)nsDataPtr;
            return nsData.bytes;
        }
    }
    @catch (NSException * e) {
        exceptionCallback((void *)CFBridgingRetain(e));
    }
    return 0;
}

const void * NSData_CreateEmpty(void (*exceptionCallback)(void * nsExceptionPtr)) {
    @try {
        NSData *data = [NSData data];
        return (__bridge_retained const void *)data;
    }
    @catch (NSException * e) {
        exceptionCallback((void *)CFBridgingRetain(e));
    }
    return NULL;
}

After that we rebuild tgz from Apple plugin and use it in Unity project.

1 Like

My fix was to change Managed Stripping Level in the Player Settings.
By default it was set to Low.
I changed it to Minimal
image

1 Like

This fixes the issue. Thanks