0
Fixed

Bolt crashing on device when EasySave plugin present in project

Tom 1 year ago updated by Lazlo Bonin (Lead Developer) 1 year ago 13

If the project contains 'Easy Save' asset from the Asset Store, then Bolt is crashing on iOS devices.

You don't have to use ES in any capacity, just download it.

The fun part is, that as long as you don't actually use Bolt, everything is fine. The crash occurs only if the scene contains a flow graph doing literally anything (in my case changing the position at start).

Any operations like regenerating build options, regenerating inspectors, running AOT pre-built are irrelevant. Just the presence of Easy Save in the project causes EXC_BAD_ACCESS.

Easy Save might be to blame somehow too, but it seems more like something on your end. Please check it as ES is a popular tool and the crash is very very nasty - it gives no clues regarding the cause. 

One thing to note - ES comes with two versions: ES2 and ES3 (backward compatibility I guess). I checked and it seems that only ES3 is conflicting with Bolt - might save you some time.

Attaching the screenshot from the crash:

Bolt Version:
1.4.4
Unity Version:
Reproduced in 2019.1.1f and 2019.1.6f
Platform(s):
Scripting Backend:
.NET Version (API Compatibility Level):

The problem seems to be more complicated than I initially thought.

Removing Easy Save did remove EXC_BAD_ACCESS and the crash, but Bolt was hanging anyway. I found out that the problem might be that I was using a List of Vector2Int as a variable in Bolt. This is the message I got in the XCode console:

Failed to deserialize behaviour.
System.Runtime.Serialization.SerializationException: Deserialization into 'Bolt.Variables' failed. ---> System.InvalidOperationException: Constructor of System.Collections.Generic.List`1[UnityEngine.Vector2Int] threw an exception when creating an instance ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.TypeInitializationException: The type initializer for 'System.Collections.Generic.List<UnityEngine.Vector2Int>' threw an exception. ---> System.ExecutionEngineException: Attempting to call method 'System.Collections.Generic.List`1[[UnityEngine.Vector2Int, UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]::.cctor' for which no ahead of time (AOT) code was generated.

This thread seems to be covering very similar issue and I see that you posted there already:

https://forum.unity.com/threads/unity-5-0-3f2-il2cpp-problem-attempting-to-call-method-system-reflection-monoproperty-getteradapt.332335/page-3

For now Easy Save seems to be a false lead, more like a problem with IL2CPP? I have a massive headache by now.

Did you create AoT stubs (Tools/Ludiq/AOT Pre-Build)?

Of course.

So removing Vector2Int from the build options and variables "solved" the issue. I am saying this with a lot of regret as I find it one of the most useful types.

Guys, I believe there is a problem with AOT Pre-build tool. The only explanation I see is that it fails to support Vector2Int as a type eligible for generic collections. Trust me, I ran AOT Build more than dozen times.

Another thing is, why the hell the presence of Easy Save 3 in the project (not scene) would crash the game at startup for a broken AOT type? 

This seems weird at least. 

Pending Review

Hi Tom,

I'm sorry you're experiencing this issue. As you pointed out, it seems like something is wrong in the AOT stubbing process, because this is definitely a JIT runtime error.

When you say you "removed Vector2int" from the build options, do you mean only from the unit options, or also from the variables on that object?

Also, I'm curious about your use of the type. IIRC it's not fully supported in Bolt 1 yet, as it shows "No inspector for Vector 2 Int". Did you create that inspector yourself?

In any case, it seems like the stubbing for variables doesn't happen properly. Can you try creating a dummy script file (anywhere in your project) with the following code:

using UnityEngine;

public class TestStub : MonoBehaviour
{
    void Start()
    {
        new List<Vector2Int>();
    }
}

And see if that resolves the issue? If so, I have an idea of how I could fix the underlying bug generally.

Hi Lazlo! I removed the Vector2Int from the build options and also from the variables. In the Flow graph I replaced List<Vector2Int> with List<string>. Had to create super units for Vector2 <-> string conversion. It's clumsy, but stable.

Regarding the missing inspector, yes I was annoyed by the lack of it. I wrote a custom property drawer for Vector2Int but it didn't help. But since I knew what I was doing, I wasn't desperate to see the values. Before I got to writing a custom inspector, I stumbled upon this nasty problem and it consumed two days of my life :D 

Since I reorganized the project, I don't have a Vector2Int in the project anymore. If you want I can add this type again and create a dummy variable to see if the error persists.

Tom

Please do! I don't have easy access to testing on iOS devices so it would help me if you could report on the potential fix.

I know this isn't of much use to you right now, but I just wanted to let you know that VectorXInts are fully supported in Bolt 2 and AOT stubbing issues should never be an issue anymore, as we generate C# code in builds instead of running from reflection.

+1

I can confirm that putting new List<Vector2Int>() into the script fixes the bug.

Working on Fix

Thanks for checking. I'll look into updating the AOT pre-build process to include used variable types.

Hi Lazlo,

I have spent another day fighting this issue and I have some more info.

So I had the same error after adding a custom type to build options. This time, a small custom static class that had some private generic methods. AOT Pre-Build was fired, of course. Also,The crash was happening only if I used Development Mode in the build process.

Rebuilding unit options couldn't fix this so I cleared my Library folder. Then I had to rebuilt the options, fire AOT Pre-build again and the bud finally went away. 

It seems that Library folder gets corrupted when adding custom types somehow :/ 

One thing I can't understand: when I was building the unit options the last time, the type I previously added wasn't there on the list! I had to add it again.. How come clearing Library folder can break Bolt like this? I thought custom types are stored in UnitOptions.db?

+1

Custom type options are stored in the ProjectSettings.asset file for Ludiq.Core. They shouldn't get erased by clearing the library, however, make sure Unity is fully closed before cleaning the library, otherwise the editor can try to reinstate backup copies of assets instantly.

I'll look into the rest of the issue when I get a minute.

Hi Tom, just following up on this.

In the next Bolt version, any variable type with a public default constructor will have it included in the AOT stubs automatically. So in that case, the hack I gave you for List<Vector2Int> would just get automatically executed in the background.