Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

LINQ stopped working on iOS (after 3.4?)

Discussion in 'Editor & General Support' started by Nevermind, Dec 22, 2011.

  1. Nevermind

    Nevermind

    Joined:
    Jun 10, 2010
    Posts:
    66
    We're making a game for iOS and Android devices, and th game code uses lots of LINQ calls. Everthing worked fine until we tried to actually run the game on an iPad. What we got was this:
    Code (csharp):
    1. ExecutionEngineException: Attempting to JIT compile method 'System.Linq.Enumerable:Sum<string, int> (System.Collections.Generic.IEnumerable`1<string>,System.Func`3<int, string, int>)' while running with --aot-only.
    Seems that AOT complation somehow screwed up and didn't compile these methods, meaning they can't be called under iOS. I narrowed the problem specifically to LINQ methods using a very simple test project. It only has one script looking like this:
    Code (csharp):
    1.  
    2. using System.Linq;
    3. using UnityEngine;
    4.  
    5. public class RandomTest : MonoBehaviour {
    6.  
    7.  void Start () {
    8.   var s=new[]{"1","1",};
    9.   UnityEngine.Debug.Log("Sum: "+s.Sum<string>(i=>2));
    10.  }
    11.  
    This code throws the same exception when running under iOS. This is really bad for us, as we use LINQ extensively.

    What is more puzzling, is that I'd made an iOS game a few months back that was using LINQ, and it compiled and ran finely. It's actuallly on AppStore right now. The game was built with Unity 3.3 IIRC.

    Did something change in 3.4 that broke AOT compilation? And what can be done about that?
     
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    There is no problem with LINQ, but AOT + Generics is a very tricky thing as it would JIT compile such code to do the best job depending on the platform which on AOT does not work. As such you can use Sum but you can basically not use Sum<> (same goes for all other <> based linqs)

    There is little to nothing you can do, even the official mono branch on mobile has the problem (you can check on the monotouch faq what limitations the mobile AOT side has, they generally apply to unity too although unity does not use that but an own thing)
     
  3. Nevermind

    Nevermind

    Joined:
    Jun 10, 2010
    Posts:
    66
    MonoTouch limitations do not mention LINQ or anything that might apply to LINQ. Also, these methods DID work prior to 3.4!
     
  4. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    The mono touch limitations talk about Generics in general not about 'generic in this and that situation' though.

    Best report a bug so it can be looked into, posting it here won't help if its really a bug.
    But it might just as well be related to fixed bugs in the mobile mono framework that Unity uses that came on 3.4 as different things were fixed from what I recall that previously pretended to work to fail then post apple DRM or on iOS 5
     
  5. Nevermind

    Nevermind

    Joined:
    Jun 10, 2010
    Posts:
    66
    The MonoTouch limitations talk about specific cases when generics do not work. Mine is not one of them.

    I've sent a bug report just now, let's see what happens.
     
  6. Mantas-Puida

    Mantas-Puida

    Joined:
    Nov 13, 2008
    Posts:
    1,864
    Your sample doesn't work on all Unity iOS versions (tested 3.3, 3.4 and upcoming 3.5), just because it hits limitations of AOT design. This does not mean that LINQ doesn't work at all, it just means that some parts of LINQ API might not work. General advice for iOS development - avoid complex code that uses many different types of generic parameters and especially if they are mixed with Reflection.
     
  7. Nevermind

    Nevermind

    Joined:
    Jun 10, 2010
    Posts:
    66
    Thanks for your response. What I still don't understand though, is how I managed to create a full game that DID compile and run on an iOS device. It used pretty much the same methods as our current game is using, and that now fail to compile.

    Anyway, if this is supposed to happen, I found a somewhat hacky workaround. Taking all LINQ-to-Objects classes from Mono sources and putting them into my project under a different namespace mostly solves this problem. Enumerable.Empty still does not work, but can be fixed easily enough (static fields of a parameter type do not work, as far as I understand).
     
  8. JJC1138

    JJC1138

    Joined:
    Feb 23, 2012
    Posts:
    89
    Just to add a litle more information for anyone Googling this issue: The 'Script Call Optimization' option under 'Other Settings' in the iOS-specific player settings can affect this. I was trying to do:

    Code (csharp):
    1. WheelCollider[] drivingWheels;
    2. [...]
    3. float averageRPM = drivingWheels.Average(i => i.rpm);
    and that worked fine when Script Call Optimization was set to 'Slow and Safe', but fails when using 'Fast but no Exceptions' with:

    Code (csharp):
    1. Unhandled Exception: System.ExecutionEngineException: Attempting to JIT compile method 'System.Linq.Enumerable:Select<UnityEngine.WheelCollider, single> (System.Collections.Generic.IEnumerable`1<UnityEngine.WheelCollider>,System.Func`2<UnityEngine.WheelCollider, single>)' while running with --aot-only.
    Getting the average manually with a simple foreach loop works fine, of course. I haven't tested this theory but I'd guess the problem is that I was working with a native class (WheelCollider) and I expect that plus the generics bumps up against the limitations that Mantas mentioned.
     
  9. JaredThirsk

    JaredThirsk

    Joined:
    Jan 17, 2010
    Posts:
    38
    Check out AOT Compatlyzer. I am using it to identify code that either needs to be replaced or that can be cleaned up automatically after compile time in a post build step. (Note that I don't use LINQ much so I ignore invocations of methods in System.* classes, but you can uncomment that line to be spammed wherever you use LINQ.)

    https://github.com/jaredthirsk/AOT-Compatlyzer
     
  10. ZammyIsOnFire

    ZammyIsOnFire

    Joined:
    Jul 7, 2014
    Posts:
    9
    Where can I find all the "dont's" for C# in iOS and current Unity 5?
     
  11. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240