I’ve seen references to similar issues in other threads, but nothing the same as this, so I thought a new thread was best. Please correct me if I’m wrong.
Our game is rather large and contains many many generics - far far too many to attempt to remove. A couple of versions ago, everything was fine on iOS. In our most recent build, we received the error below.
We are using (currently) Unity 5.1.4f1. After receiving the error we tried updating to 5.2.2p4, and then 5.2.3 when that released. Neither of these helped and we are currently trying 5.3.0 RC1.
This is a serious blocker for us and we currently have no way around it, any help would be much appreciated.
GetValues() is a generic method that takes an unconstrained type , which is intended to be an enum, and returns all enum values for that type.
It’s hard to say from this error if this should work with AOT, but I have a few questions to try to better understand the situation. Does a similar error work with the Mono scripting backend on any version (maybe from 5.1.4f1)? Do you know what version this worked at with iOS? And what scripting backend were you using then (Mono or IL2CPP)?
Note that a newer version will likely not help here, as we synchronize the IL2CPP scripting backend across all of the latest versions, so if 5.2.3 doesn’t work, then 5.3.0RC1 likely won’t work either, as they have the same code for IL2CPP.
We’ve just tried a build with Mono scripting backend, which didn’t work either, but got a slightly different error and earlier than the one posted. The new error is posted below, with some call stack info removed. We haven’t used Mono as the scripting backend for a while, since at least Unity 5.0.
The last successful build we had was using Unity 5.1.4f1 and using IL2CPP. This was an earlier version of our game, so I assume a change in game code caused the error to appear. Although the method “GetValues()” has existed for a long time and been called with that parameter before.
These errors can be difficult to track down, unfortunately. The best option might be a bisect using your source control system (if possible) with that single 5.1.4f1 version of Unity, starting with the revision of the project where this error did not occur.
These problems usually show up in generic virtual methods when they are used with value types. So I think that CopyTo on the ICollection interface here is a generic virtual method, and it is used with a enum, which is a value type. the problem happens when that method (CopyTo, I suspect here) is not used anywhere else in the code, so the IL2CPP AOT compiler doesn’t notice it to generate the code for it.
If you can track down the change in the project that caused this, we should be able to determine a work around.
OK, we’ll try doing that. Unfortunately it may take a while, but I’ll get back to you as soon as I can.
Do you think this a problem with our code or that our code has surfaced a problem with the IL2CPP interpreter?
I’m going to guess the problem is in your code, at least in the sense that the code in your project changed in some way to be no longer AOT-friendly. Since this did not happen with an earlier version of your project in 5.1.4f1 and does happen with a later version of your project in the same Unity version, then I think the breaking change must be in your code.
However, if you can track down what that change is, I am interested to better understand it to see if it is something that we can support in IL2CPP in the future.
We’ve narrowed it down to a specific commit and are now going through the scripts in that commit (our Mac is terribly slow so builds take a while). Is there anything we can look out for? Generic classes, extensions or some such?
Hi again, Josh. We’ve narrowed it down to one class and managed to work around it for now.
I’ve attached the original class (when it was working), the new class (which caused the error), and our work around (which essentially contains both sets of code.
The change was around the GetReward() method, which was updated to use GetInt(), GetSkill() etc.
Adding the GetReward() back in and making sure that it was referenced somewhere (GetSummary()) fixes the issue.
After our launch, the New Year, we will work on a repro project if that would help you guys.
Thanks for tracking this down. Yes, if you can put together a repro project for this, we would like to have a look at it. I’m not sure yet that is somethings we can support for AOT, but it looks like it might be possible, so I would like to try. No hurry though, just ping me here when you submit the bug report. Thanks!
Hi again Josh. We struggled to produce a repro project. Our project is massive unfortunately
Though we found out that it wasn’t the generic method we thought it was. It turns out that there were two static method that weren’t used underneath the GetReward() method. One of these had a List as a parameter, which was the type that the EngineExecutionException was thrown with. We’re triple-checking that it definitely is this at the moment, but it seems like removing those methods causes an AOT exception, and adding them back in fixes it. Not sure if this helps you narrow anything down at all?
Thanks for the information. It might be possible that the existence of those methods caused AOT for some type (maybe List) that was used elsewhere at runtime. So not having those methods lead to the EngineExecutionException when the type was not found at runtime.