Skip to content
This repository has been archived by the owner on Oct 6, 2023. It is now read-only.

Fix AOT using link.xml

Kalle Jillheden edited this page Jan 7, 2020 · 2 revisions

The problem

Let's say you get this error:

Newtonsoft.Json.JsonSerializationException : Unable to find a constructor to use for type MyCSharpClass. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path ''.

First off, you've probably set everything up correctly. It's just missing that one secret ingredient: bytecode-stripping proofing.

Our recommended around this is using the AotHelper, however there's a big unsolvable flaw with the AotHelper and that is if the type is inaccessible due to non-public accessibility modifiers.

Ex: when you come across a private or internal class.

99 times out of 100 you have a class you're deserializing, but during that procedure when Newtonsoft.Json is trying to instantiate the class you want to receive the constructor has been long gone removed by IL2CPP's bytecode stripping.

Side note: The IL2CPP compiler has this neat trick of removing what it thinks is unused code. This includes unused assemblies, classes, methods, and even down to the property level. The constructor is no exception, it's just a special type of method. You can read the What even is AOT wiki page to get a more reinforced understanding of why IL2CPP does this.

Let's dive in!

The fix

In this example, let's assume we're having problems with our MyCSharpClass class that lives inside /Assets/Scripts/Models/MyCSharpClass.cs. We're also put our class in the namespace Models. Our file could look like this:

// MyCSharpClass.cs
namespace Models
{
    public class MyCSharpClass
    {
    }
}

Let's also assume we are not using any assembly definitions (docs.unity3d.com) and therefore our assembly is the default name given by unity: AssemblyCSharp.

Step 1 - Create (or reuse) a link.xml file

What this file is here to do is to disable the bytecode stripping mentioned above for the members we decide.

The link.xml file can live anywhere within your /Assets folder, at any subdirectory. Ex: at /Assets/link.xml. You can even have multiple. If you have multiple they all aggregate in such a way that all bytecode stripping disabling declarations will be applied.

This would be the content of an empty link.xml file:

<linker>
</linker>

Highly suggest you get yourself familiar with the XML syntax. If you're familiar to HTML then you're all set as HTML is based on XML.

The <linker> needs to be the root node of the document for Unity to acknowledge your settings.

Step 2 - Disable stripping of our constructor

<linker>
    <assembly fullname="AssemblyCSharp">
        <type fullname="Models.MyCSharpClass">
            <method signature="System.Void .ctor()"/>
        </type>
    </assembly>
</linker>

Step 3 - Rebuild with IL2CPP and try again

Build your Unity product again using IL2CPP and enjoy living without that error!

Note about how specific you should be in link.xml

Be as specific as possible. The bytecode stripping that IL2CPP performs is something you want. Thanks to the stripping your build size is lowered to a fraction of what it could have been. Stay professional!

Wiki page: Reference link.xml

To know everything you can omit from bytecode stripping using a link.xml file visit the wiki page linked in the header above.

Clone this wiki locally