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);
}
}
}
Thanks for the suggestion! I’d been struggling with mysterious SIGABRT crashes with no useful details. It turned out to be related to code stripping. Even though the Apple plugin packages include link.xml, Unity didn’t seem to respect them. Moving those link.xml files under Assets fixed the issue for me. Alternatively, setting Code Stripping to Low should also resolve it.