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?
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 ---
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:
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);
}
}
}