LoginSignup
16
14

More than 5 years have passed since last update.

IL2CPPでLINQのAOTエラーが結構改善されたような気がする

Last updated at Posted at 2016-02-22

IL2CPPでLINQのAOTエラーが結構改善されたような気がする

という話

以下の記事の通りかわいいかわいいLINQちゃんはiOSだと気をつけて使わないとクラッシュする。
と言う問題がMonoの時にはありました。
Unity + iOSのAOTでの例外の発生パターンと対処法とか
Unity+iOSでエラーになるLINQのまとめ - Qiita

どうやらIL2CPPになった段階で結構解消されたような気がするので、テストコード書いてみてクラッシュするかなー?しないかなー?って確認したところ以下のメソッドは全部AOTでクラッシュしませんでした。(手元の環境はXcode7,iOS9,Unity5.3.2p3で確認)

Unity+iOSでエラーになるLINQのまとめ - Qiita
を参考に以下のクラッシュしていたメソッドのみ検証です。

  • Average
  • Max
  • Min
  • Sum
  • FirstOrDefault
  • Last
  • LastOrDefault
  • Single
  • SingleOrDefault
  • ToDictionary
  • ToLookup
  • Join
  • OrderBy
  • OrderByDescending

クラッシュ本当にしないのかは検証不足なのですが、なんかいい感じに解決してそうなので公開しておきます。(だれか追試してー)


using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;

public struct SimpleStruct{
    public int Value{get;set;}
    public SimpleStruct(int value):this(){
        Value = value;
    }
}

public class SimpleClass{
    public int Value{get;set;}
    public SimpleClass(int value){
        Value = value;
    }
}

public class AOTTest : MonoBehaviour {

    void OnGUI()
    {
        if(GUILayout.Button("Test Average"))
        {
            var ave = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).Select(s => s.Value).Average();
            Debug.Log("Average:" + ave);
        }

        if(GUILayout.Button("Test Max"))
        {
            var max = new int[10].Select(_=>new SimpleClass(Random.Range(0,1000))).Select(s => s.Value).Max();
            Debug.Log("Max:" + max);
        }

        if(GUILayout.Button("Test Min"))
        {
            var min = new int[10].Select(_=>new SimpleClass(Random.Range(0,1000))).Select(s => s.Value).Min();
            Debug.Log("Min:" + min);
        }

        if(GUILayout.Button("Test Sum"))
        {
            var sum = new int[10].Select(_=>new SimpleClass(Random.Range(0,1000))).Select(s => s.Value).Sum();
            Debug.Log("Sum:" + sum);
        }

        if(GUILayout.Button("Test FirstOrDefault"))
        {
            var first = new int[10].Select(_=>Random.Range(0,1000)).FirstOrDefault();
            Debug.Log("First:" + first);
        }

        if(GUILayout.Button("Test Last"))
        {
            var last = new int[10].Select(_=>Random.Range(0,1000)).Last();
            Debug.Log("Last:" + last);
        }

        if(GUILayout.Button("Test LastOrDefault"))
        {
            var last = new int[10].Select(_=>Random.Range(0,1000)).LastOrDefault();
            Debug.Log("LastOrDefault:" + last);
        }

        if(GUILayout.Button("Test Single"))
        {
            var value = new int[10].Select((i,n)=>n).Take(1).Single();
            Debug.Log("Single:" + value);
        }

        if(GUILayout.Button("Test SingleOrDefault"))
        {
            var value = new bool[10].Select((i,n)=>n).Take(1).SingleOrDefault();
            Debug.Log("SingleOrDefault:" + value);
        }

        if(GUILayout.Button("Test Join"))
        {
            var a = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).ToArray();
            var dic = a.Join(a,i=>i.Value,o => o.Value,(i,o)=> i.Value + o.Value).ToArray();
            Debug.Log (dic);
        }


        if(GUILayout.Button("Test ToDictionary 1"))
        {
            var dic = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).ToDictionary (skill => skill.Value);
            DictionaryLog(dic);
        }

        if(GUILayout.Button("Test ToDictionary 2"))
        {
            var dic = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).ToDictionary (skill => skill.Value,EqualityComparer<int>.Default);
            DictionaryLog(dic);
        }

        if(GUILayout.Button("Test ToLookup 1"))
        {
            var dic = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).ToLookup (skill => skill.Value);
            LookupLog(dic);
        }

        if(GUILayout.Button("Test ToLookup 2"))
        {
            var dic = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).ToLookup (skill => skill.Value,EqualityComparer<int>.Default);
            LookupLog(dic);
        }

        if(GUILayout.Button("Test OrderBy")){
            var a = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).OrderBy( k => k.Value);
            foreach (var item in a) {
                Debug.Log("Sort"+item.Value);
            }
        }

        if(GUILayout.Button("Test OrderByDescending")){
            var a = new int[10].Select(_=>new SimpleStruct(Random.Range(0,1000))).OrderByDescending( k => k.Value);
            foreach (var item in a) {
                Debug.Log("Sort"+item.Value);
            }
        }

    }

    private void DictionaryLog<K,T>(Dictionary<K,T> dict)
    {
        foreach(var kv in dict)
        {
            Debug.Log(kv.Key + ":" + kv.Value);
        }
    }

    private void LookupLog<K,T>(ILookup<K,T> dict)
    {
        foreach(var kv in dict)
        {
            Debug.Log(kv.Key + ":" + kv.ToArray());
        }
    }



}



こういう書捨てのコード書くときレガシーGUI便利だと思います。

やってないこと

  • 他のメソッドが死んでないかのテスト
  • 他のバージョンでのテスト
16
14
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
14