Unity/IOS Build Error for Gamelift Project -- System.Configuration.ConfigurationManager::get_AppSettings

I am having a persistent issue in building my Unity (version 2020.2.0a15) game, which utilizes AWS Gamelift, on iOS. It runs fine on simulator, and I can build and successfully run on my mac with all of my networking, matchmaking, etc. working.

However, when I try to build this to my iOS device through xcode (12.3), I get the error below, which seems related to IL2CPP based on my search so far.

The last line of the stack trace is: System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings

The full version is at the end of the post to not crowd it out :slight_smile:

I have spent a few days trying to fix this myself, but have been unable to make progress. The common issues referenced are:

  • link.xml not being set up, so the code gets stripped. I have one, posting below
  • AWS config not being set up. I have one, posting below
  • log4net not being configured. On my local version, I have a log4net.xml set up, which is being read and I confirmed the appender is working and logging to a file on my dev pc when I run in the simulator
  • AWS being fundamentally incompatible with Il2CPP (which I hope isn’t true, and seems wrong if there are gamelift games on ios?)

Could somebody please help me figure out how to fix this and get gamelift working with IL2CPP builds? I saw a related thread here, but with less details and no solutions.

I realize this could be a unity issue, but was hoping someone might know a fix.

References:

My log4net.xml file, in my Assets folder:

<?xml version="1.0" encoding="utf-8"?>
<log4net>

  <appender name="EventLog" type="log4net.Appender.RollingFileAppender">
    <file value="events.log" />
    <appendToFile value="true" />
    <rollingStyle value="Once" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="1MB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date %-5level in [%thread] %logger%newline%message%newline" />
    </layout>
  </appender>

  <root>
    <level value="DEBUG" />
    <appender-ref ref="EventLog" />
  </root>
  
</log4net>

I initialize this in LoggingConfig.cs and (as you can see by the comments lol) confirmed it exists/is readable.

using System.IO;
using log4net.Config;
using UnityEngine;

public static class LoggingConfiguration
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    private static void ConfigureLogging()
    {
        //Debug.Log("configuring xml from" +  $"{Application.dataPath}/assets/resources/log4net.xml");
        FileInfo fi = new FileInfo($"{Application.dataPath}/log4net.xml");
        XmlConfigurator.Configure(new FileInfo($"{Application.dataPath}/log4net.xml"));
        //Debug.Log(fi.FullName);
        //Debug.Log(fi.Exists);
        //Debug.Log(fi.LastAccessTime);
    }
}

In Assets/Resources I have configured my link.xml VERY permissively:

<linker>
    <assembly fullname="UnityEngine"> 
        <type fullname="UnityEngine.Networking.UnityWebRequest" preserve="all" /> 
        <type fullname="UnityEngine.Networking.UploadHandlerRaw" preserve="all" /> 
        <type fullname="UnityEngine.Networking.UploadHandler" preserve="all" />
        <type fullname="UnityEngine.Networking.DownloadHandler" preserve="all" /> 
        <type fullname="UnityEngine.Networking.DownloadHandlerBuffer" preserve="all" /> 
    </assembly>
    <assembly fullname="AWSSDK.Core" preserve="all"/>
    <assembly fullname="AWSSDK.DynamoDBv2" preserve="all"/>
    <assembly fullname="AWSSDK.GameLift" preserve="all"/>
    <assembly fullname="AWSSDK.SimpleNotificationService" preserve="all"/>
    <assembly fullname="Microsoft.Bcl.AsyncInterfaces" preserve="all"/>
    <assembly fullname="Newtonsoft.Json" preserve="all"/>
    <assembly fullname="System.Buffers" preserve="all"/>

(the post editor’s being buggy for formatting code so I’ve split it into 2 quote blocks for the post, but it’s one file)

    <assembly fullname="System.Object" preserve="all"/>
    <assembly fullname="System.Numeric.Vectors" preserve="all"/>
    <assembly fullname="System.Runtime.CompilerServices.Unsafe" preserve="all"/>
    <assembly fullname="System.Text.Encodings.WEb" preserve="all"/>
    <assembly fullname="System.Threading.Tasks.Extensions" preserve="all"/>
    <assembly fullname="System.ValueTuple" preserve="all"/>
    <assembly fullname="Google.Protobuf" preserve="all"/>
    <assembly fullname="log4net" preserve="all"/>
    <assembly fullname="System.Configuration" preserve="all"/>
    <assembly fullname="mscorlib">
        <namespace fullname="System.Security.Cryptography" preserve="all"/>
    </assembly>
    <assembly fullname="System">
        <namespace fullname="System.Security.Cryptography" preserve="all"/>
    </assembly>
    <assembly fullname="AWSSDK.CognitoIdentity" preserve="all"/>
    <assembly fullname="AWSSDK.SecurityToken" preserve="all"/>
</linker>

Lastly, I have a basic awsconfig.xml file in Assets/Resources:

<?xml version="1.0" encoding="utf-8"?>
<aws correctForClockSkew="true" region="us-west-2">
    <logging logTo="UnityLogger"
             logResponses="Always"
             logMetrics="true"
             logMetricsFormat="JSON" />
    <s3 useSignatureVersion4="true" />
</aws>

Full stack trace from xcode debug window:

log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.LogLog…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager.GetVersionInfo () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.LogLog…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager.GetVersionInfo () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.LogLog…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager.GetVersionInfo () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager.GetVersionInfo () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager.GetVersionInfo () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager…cctor () [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.NotSupportedException: System.Configuration.ConfigurationManager::get_AppSettings
at System.Configuration.ConfigurationManager.get_AppSettings () [0x00000] in <00000000000000000000000000000000>:0
at log4net.Util.SystemInfo.GetAppSetting (System.String key) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.DefaultRepositorySelector.ConfigureRepository (System.Reflection.Assembly assembly, log4net.Repository.ILoggerRepository repository) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.DefaultRepositorySelector.CreateRepository (System.Reflection.Assembly repositoryAssembly, System.Type repositoryType, System.String repositoryName, System.Boolean readAssemblyAttributes) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.DefaultRepositorySelector.CreateRepository (System.Reflection.Assembly repositoryAssembly, System.Type repositoryType) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.DefaultRepositorySelector.GetRepository (System.Reflection.Assembly repositoryAssembly) [0x00000] in <00000000000000000000000000000000>:0
at log4net.Core.LoggerManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Reflection.Assembly repositoryAssembly, System.String name) [0x00000] in <00000000000000000000000000000000>:0
at log4net.LogManager.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Controller…cctor () [0x00000] in <00000000000000000000000000000000>:0
2020-12-22 11:33:18.190362-0800 TSBRV2[26335:3201119] Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x1181a4a50>.
UnloadTime: 2.203000 ms
False
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:Log(Object)
Controller:Start()

Ignore me - called to open Console
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:LogError(Object)
Controller:Start()

ArgumentNullException: Value cannot be null.
Parameter name: obj
at System.Threading.Monitor.ReliableEnterTimeout (System.Object obj, System.Int32 timeout, System.Boolean& lockTaken) [0x00000] in <00000000000000000000000000000000>:0
at System.Threading.Monitor.ReliableEnter (System.Object obj, System.Boolean& lockTaken) [0x00000] in <00000000000000000000000000000000>:0
at System.Threading.Monitor.Enter (System.Object obj, System.Boolean& lockTaken) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.AWSConfigs.TraceListeners (System.String source) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.Internal.Util.TraceSourceUtil.GetTraceSourceWithListeners (System.String name, System.Diagnostics.SourceLevels sourceLevels) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.Internal.Util.TraceSourceUtil.GetTraceSource (System.Type targetType, System.Diagnostics.SourceLevels sourceLevels) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.Internal.Util.TraceSourceUtil.GetTraceSource (System.Type targetType) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.Internal.Util.InternalSystemDiagnosticsLogger…ctor (System.Type declaringType) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.Internal.Util.Logger.GetHashCode () [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.Internal.Util.Logger.GetLogger (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
at Amazon.Runtime.CredentialManagement.SharedCredentialsFile…ctor () [0x00000] in <00000000000000000000000000000000>:0
at GameLiftClient.CreateGameLiftClient () [0x00000] in <00000000000000000000000000000000>:0
at GameLiftClient…ctor () [0x00000] in <00000000000000000000000000000000>:0
at NetworkManager…ctor () [0x00000] in <00000000000000000000000000000000>:0
at UnityEngine.GameObject.AddComponent (System.Type componentType) [0x00000] in <00000000000000000000000000000000>:0
at UnityEngine.GameObject.AddComponent[T] () [0x00000] in <00000000000000000000000000000000>:0
at Controller.Start () [0x00000] in <00000000000000000000000000000000>:0
UnityEngine.GameObject:AddComponent(Type)
UnityEngine.GameObject:AddComponent()
Controller:Start()

I assume as you’re building for iOS you are using the AWS GameLift Client SDK? These are generally managed by the https://aws.amazon.com/sdk-for-net/ AWS C# SDK team.

I did see this, https://forum.unity.com/threads/aws-gamelift-make-notsupportedexeption-when-use-il2cpp.892807/ and this https://stackoverflow.com/questions/65029735/unity-using-aws-gamelift-editor-fine-but-notsupportedexception-in-build-to-ios

So I would suspect this is a IL2CPP/Unity issue where certain system libs are not fully implemented on iOS (hence its failing on device).

Did you follow the Unity advice here: https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/unity-special.html?

Not sure if others have built this way, will ping the GameLift team tomorrow to see if they have any advice (but a response may be slow due to the holidays).

You could also try the https://forums.aws.amazon.com/forum.jspa?forumID=61 as this is really a how to use the AWS C# SDKs in Unity on iOS issue and not specific it seems to the GameLift SDK

  • I would suspect you may this issue using a client for any AWS service currently.

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

Thanks, I appreciate it. I’ll check those links.

It’s definitely the AWS Gamelift Client SDK (available in nuget) – I’m using a realtime node.js server so the server code lives totally outside of my client files.

I confirmed I can reproduce this really easily by building a game with an empty canvas and the following simple class with my config details. I also posted on the unity forums: https://answers.unity.com/questions/1798933/how-do-i-fix-this-issue-with-systemconfigurationco.html and can follow up here if I get an answer there.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Amazon;
using Amazon.GameLift;
using Amazon.Runtime;
using Amazon.GameLift.Model;
using Amazon.Runtime.CredentialManagement;
using System;

public class TestGameLift : MonoBehaviour
{

    public Guid myName;
    private Amazon.GameLift.Model.PlayerSession psession = null;
    public string aliasId = "<alias>";
    public static readonly string profileName = "<profile>";
    public AmazonGameLiftClient aglc = null;
    public AWSCredentials credentials;
    public AmazonGameLiftConfig config;


    // Start is called before the first frame update
    void Start()
    {
        string ticketId = Guid.NewGuid().ToString();
        string playerId = Guid.NewGuid().ToString();

        var options = new CredentialProfileOptions
        {
            AccessKey = "<key>",
            SecretKey = "<key>"
        };
        CredentialProfile profile = new CredentialProfile("iam", options);
        profile.Region = Amazon.RegionEndpoint.USWest2;
        var sharedFile = new SharedCredentialsFile();
        sharedFile.RegisterProfile(profile);

        credentials = profile.GetAWSCredentials(null);
        aglc = new AmazonGameLiftClient(credentials, Amazon.RegionEndpoint.USWest2);

        ticketId = Guid.NewGuid().ToString();

        AttributeValue skill = new AttributeValue
        {
            N = 1.0
        };

        Player player = new Player
        {
            PlayerId = playerId,
            LatencyInMs = new Dictionary<string, int>{
                { "us-west-2" , 1 }
            },
            PlayerAttributes = new Dictionary<string, AttributeValue>
            {
                { "skill", skill }
            }
        };

        var mmRequest = new StartMatchmakingRequest();
        mmRequest.Players = new List<Player> { player };

        mmRequest.TicketId = ticketId;
        mmRequest.ConfigurationName = "defaultMatchmakingConfiguration";

        StartMatchmakingResponse mmResponse = aglc.StartMatchmaking(mmRequest);
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("Hi!");
        
    }
}

Hey Pip, just following up on this thread. I got this working (on iOS) by switching to AWS 2.0 SDKs from the zip in this documentation page: https://aws.amazon.com/blogs/developer/referencing-the-aws-sdk-for-net-standard-2-0-from-unity-xamarin-or-uwp/

I had to make some code changes (have to use async functions for many network calls, but that should be moved to lambda once I’m done with my proof of concept anyways).

I used the libraries from the realtime package as they were, I think, as they only build the one version. After this my game works and I can call matchmaking & query my dynamodb on both my editor, mac builds, and ios builds.

Unfortunately, now I am running into issues with TLS not working on ios builds, but as far as this specific error it’s resolved for me :slight_smile: