• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by Julian42 · Aug 03, 2012 at 04:46 PM · iphonejit

JIT exception in Unity iPhone

Hi, I have my project working in the editor, but there is an error when runing on my iPad. This is the exception:

ExecutionEngineException: Attempting to JIT compile method 'TerrainData:.ctor ()' while running with --aot-only.

at TerrainData..cctor () [0x00000] in :0 Rethrow as TypeInitializationException: An exception was thrown by the type initializer for TerrainData

I suspect my use of generics is causing a problem, but since I am new to C#/Unity I am befuddled!

Here is the entire class:

 public class TerrainData {
  private static readonly TerrainData instance = new TerrainData();
  
  enum roomWallType { exterior, interior };
  
  //a set of slope prefabs indexed by type then variant
  public List<List<GameObject>> slopePrefabs;
  public List<GameObject> roomWallJoin;  //joiner bits for room walls
  
  public List<GameObject>[] roomWall;
  public List<GameObject>[] roomWin;
  public List<GameObject>[] roomDoor;
  public List<GameObject>[] roomLockDoor;
  public List<GameObject> moveHighlightPrefabs;
  
  //Defines all possible slopes based on height level of four corners (hence 4 dimensional array)
  public MapElement[,,,] slopes; 
  public MapElement[,,,,,,,] wallJoins;
  
  
  //define a slope type by the height level of each corner (only one of the four possible orientations)
  //this data is based on the template graphics (with first corner at x0,y1 in Blender file)
  public int[,] slopeTypes;
  //defined by edge types (external=1, internal=2) on each of four spokes
  public int[,] wallJoinTypes;
 
  
  
  private TerrainData() {
  slopePrefabs = new  List<List<GameObject>>();
  
  
  roomWallJoin = new List<GameObject>();  //joiner bits for room walls
  roomWall = new List<GameObject>[2];
  roomWin = new List<GameObject>[2];
  roomDoor = new List<GameObject>[2];
  roomLockDoor = new List<GameObject>[2];
  moveHighlightPrefabs = new List<GameObject>();
  
  
  slopes = new MapElement[3,3,3,3];
  wallJoins = new MapElement[3,3,3,3,3,3,3,3];
  //define a slope type by the height level of each corner (only one of the four possible orientations)
  //this data is based on the template graphics (with first corner at x0,y1 in Blender file)
  slopeTypes = new int[,] { //represents height level of each corner
  {0,0,0,0},  //floor type
  {1,1,1,1},  //floor type
  {2,2,2,2},  //floor type
  {1,1,0,0},
  {2,2,1,1},
  {1,0,0,0},
  {2,1,1,1},
  {1,1,0,1},
  {2,2,1,2},
  {1,1,0,2},
  {1,2,0,0},
  {1,2,0,1},
  {2,0,0,0},
  {2,1,0,0},
  {2,1,0,1},
  {2,1,0,2},
  {2,2,0,0},
  {2,2,0,1},
  {2,2,0,2},
  {1,0,1,0},
  {2,1,2,1},
  {2,0,2,0},
  {2,0,1,0},
  {2,0,2,1} };
  
  
  //defined by edge types (external=1, internal=2) on each of four spokes
  wallJoinTypes = new int[,] {
  {0,0,0,0,0,0,1,2},
  {0,0,0,0,0,0,2,1},
  {0,0,0,0,0,0,2,2},
  {0,0,1,2,0,0,2,1},
  {0,0,2,2,0,0,2,2},
  {1,1,1,2,0,0,2,1},
  {1,2,0,0,0,0,2,1},
  {1,2,2,1,1,2,2,1},
  {1,2,2,2,0,0,2,1},
  {1,2,2,2,2,2,2,1},
  {2,1,0,0,0,0,1,2},
  {2,1,1,2,0,0,2,2},
  {2,2,0,0,0,0,2,2},
  {2,2,2,1,0,0,1,2},
  {2,2,2,2,0,0,2,2},
  {2,2,2,2,2,2,2,2} }; 
  }
  
  
  
  
  
  public static TerrainData Instance
  {
  get 
  {
  return instance; 
  }
  }
  
  
  // Terrain\Floors\Template\Template_slope_0000
  public void LoadSlopes() {
  string envName = "Template";
  string slopePathStub = String.Format("Terrain/Floors/{0}/{0}_slope_", envName);
  for (int i=0; i< slopeTypes.GetLength(0); i++) {
  string slopeID = String.Format("{0}{1}{2}{3}", slopeTypes[i,0], slopeTypes[i,1], slopeTypes[i,2], slopeTypes[i,3]);
  string slopeFolder = slopePathStub + slopeID;
  List<GameObject> slopeVariants = new List<GameObject>();
  GameObject slope = null;
  int variantNum = 0;
  while (true) {
  string fileName = slopeFolder + String.Format( "/{0}_slope_{1}_{2}"  , envName, slopeID, variantNum );
  slope = LoadPrefab(fileName);
  if (slope == null) break;
  slopeVariants.Add(slope);
  variantNum++;
  }
  slopePrefabs.Add(slopeVariants);
  }
  }
  
  
  public void LoadMoveHighlights() {
  string pathStub = "Interface/MoveHighlights/MH_";
  for (int i=0; i< slopeTypes.GetLength(0); i++) {
  string slopeID = String.Format("{0}{1}{2}{3}", slopeTypes[i,0], slopeTypes[i,1], slopeTypes[i,2], slopeTypes[i,3]);
  string pathName = pathStub + slopeID;
  GameObject highlight = null;
  highlight = LoadPrefab(pathName);
  moveHighlightPrefabs.Add(highlight);
  }
  } 
  
  
  /* builds four rotations for each slope type in a 4D array, which is then used in the map building
  */
  public void BuildSlopeElements() {
  MapElement slopeElement;
  slopeElement.valid = true;
  for (int i=0; i< slopeTypes.GetLength(0); i++) {
  int c1 = slopeTypes[i,0];
  int c2 = slopeTypes[i,1];
  int c3 = slopeTypes[i,2];
  int c4 = slopeTypes[i,3];
  slopeElement.typeID = i;
  slopeElement.orientation = 0;
  slopes[c1,c2,c3,c4] = slopeElement;
  slopeElement.orientation = 1;
  slopes[c4,c1,c2,c3] = slopeElement;
  slopeElement.orientation = 2;
  slopes[c3,c4,c1,c2] = slopeElement;
  slopeElement.orientation = 3;
  slopes[c2,c3,c4,c1] = slopeElement;
  }
  }
  
  public GameObject GetSlopePrefab( int slopeID, int variant ) {
  //if (variant >= slopePrefabs[slopeID].Count) variant = 0;
  return slopePrefabs[slopeID][variant];
  }
 
  public GameObject GetWallJoinPrefab( int joinID ) {
  return roomWallJoin[ joinID ];
  } 
  
  public int GetNumVariants( int slopeID ) {
  return slopePrefabs[slopeID].Count;
  }
  
  public int GetNumRoomWallVariants( RoomWallCell.BaseType baseType, RoomWallCell.SubType subType ) {
  switch (subType) {
  case RoomWallCell.SubType.wall:
  return roomWall[(int)baseType-1].Count;
  case RoomWallCell.SubType.window:
  return roomWin[(int)baseType-1].Count;
  case RoomWallCell.SubType.door:
  return roomDoor[(int)baseType-1].Count;
  case RoomWallCell.SubType.lockDoor:
  return roomLockDoor[(int)baseType-1].Count;
  }
  return 1;
  } 
  
  
  public int SetValidSlopeVariant( int slopeID, int variant) {
  if ( variant >= slopePrefabs[slopeID].Count) variant = 0;
  return variant;
  }
  
  
  //will return null if no such object
  private GameObject LoadPrefab(string pathName) {
  GameObject prefab = Resources.Load(pathName) as GameObject;
  //if (prefab == null) {
  //Debug.Log( String.Format("Could not load prefab [{0}]", pathName) );
  //}
  return prefab;
  }
  
  
  public void LoadRoomWalls() {
  string envName = "Template";
  string stub = String.Format("Terrain/Rooms/RoomWalls/{0}", envName);
  GameObject wall = null;
  int variantID;
  string[] wallTypes = {"ext", "int"};
  for (int i=0 ; i<2; i++) {
  //walls
  variantID = 0;
  roomWall[i] = new List<GameObject>();
  while (true) {
  string fname = String.Format( "{0}/{1}_wall_{2}_{3}", stub, envName, wallTypes[i], variantID );
  wall = LoadPrefab( fname );
  if (wall == null) break;
  roomWall[i].Add( wall );
  variantID ++;
  }
  //windows
  variantID = 0;
  roomWin[i] = new List<GameObject>();
  while (true) {
  string fname = String.Format( "{0}/{1}_win_{2}_{3}", stub, envName, wallTypes[i], variantID );
  wall = LoadPrefab( fname );
  if (wall == null) break;
  roomWin[i].Add( wall );
  variantID ++;
  }
  //doors
  variantID = 0;
  roomDoor[i] = new List<GameObject>();
  while (true) {
  string fname = String.Format( "{0}/{1}_door_{2}_{3}", stub, envName, wallTypes[i], variantID );
  wall = LoadPrefab( fname );
  if (wall == null) break;
  roomDoor[i].Add( wall );
  variantID ++;
  }
  //locked doors
  variantID = 0;
  roomLockDoor[i] = new List<GameObject>();
  while (true) {
  string fname = String.Format( "{0}/{1}_lockdoor_{2}_{3}", stub, envName, wallTypes[i], variantID );
  wall = LoadPrefab( fname );
  if (wall == null) break;
  roomLockDoor[i].Add( wall );
  variantID ++;
  } 
  }
  }
  
  
  public GameObject GetRoomWall( RoomWallCell.BaseType baseType, RoomWallCell.SubType subType, int variant ) {
  //probably should check if valid variant
  switch (subType) {
  case RoomWallCell.SubType.wall:
  return roomWall[(int)baseType-1][variant];
  case RoomWallCell.SubType.window:
  return roomWin[(int)baseType-1][variant];
  case RoomWallCell.SubType.door:
  return roomDoor[(int)baseType-1][variant];
  case RoomWallCell.SubType.lockDoor:
  return roomLockDoor[(int)baseType-1][variant];
  }
  return null;
  }
  
  
  public void LoadRoomWallJoins() {
  string envName = "Template";
  string stub = String.Format("Terrain/Rooms/RoomWalls/{0}/{0}_walljoin_", envName);
  for (int i=0; i < wallJoinTypes.GetLength(0); i++ ) {
  string ID = "";
  for (int j=0; j<8; j++) {
  ID += wallJoinTypes[i,j].ToString();
  }
  roomWallJoin.Add( LoadPrefab( stub + ID ) );
  }
  
  }
  
  
  public void BuildWallJoinElements() {
  MapElement slopeElement;
  slopeElement.valid = true;
  for (int i=0; i< wallJoinTypes.GetLength(0); i++) {
  int c1 = wallJoinTypes[i,0];
  int c2 = wallJoinTypes[i,1];
  int c3 = wallJoinTypes[i,2];
  int c4 = wallJoinTypes[i,3];
  int c5 = wallJoinTypes[i,4];
  int c6 = wallJoinTypes[i,5];
  int c7 = wallJoinTypes[i,6];
  int c8 = wallJoinTypes[i,7];
  slopeElement.typeID = i;
  slopeElement.orientation = 0;
  wallJoins[c1,c2,c3,c4,c5,c6,c7,c8] = slopeElement;
  slopeElement.orientation = 1;
  wallJoins[c7,c8,c1,c2,c3,c4,c5,c6] = slopeElement;
  slopeElement.orientation = 2;
  wallJoins[c5,c6,c7,c8,c1,c2,c3,c4] = slopeElement;
  slopeElement.orientation = 3;
  wallJoins[c3,c4,c5,c6,c7,c8,c1,c2] = slopeElement;
  }
  }
  
  
  /* load all prefabs and prepare data */
  public void MakeData() {
  LoadSlopes();
  BuildSlopeElements();
  LoadRoomWalls();
  LoadRoomWallJoins();
  BuildWallJoinElements();
  LoadMoveHighlights();
  }
  
 }
 
 
  
Comment

People who like this

0 Show 7
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Aug 03, 2012 at 05:49 PM 0
Share

I have never seen an eight dimensional array before - what on earth are you storing in wallJoins? Surely that isn't fully populated?

Anyway Generics are fine on the iPhone but I've never used an array of lists (though lists of lists I use all the time). Can you post any initialised variables and the constructor?

avatar image Julian42 · Aug 04, 2012 at 06:04 AM 0
Share

Thanks for your reply, whydoidoit!

The wall joins can join in up to four directions with either internal or external wall surfaces on each side. The 8D array is used to access the correct prefab for a particular situation.

I posted the entire class to see if you can spot anything.

avatar image chrisjjones · Aug 04, 2012 at 02:23 PM 0
Share

What is your API Compatibility Level and Stripping Level in your Build settings?

avatar image Julian42 · Aug 04, 2012 at 03:04 PM 0
Share

API compatibility level is .NET 2.0 Stripping level is disabled

avatar image whydoidoit · Aug 04, 2012 at 03:08 PM 0
Share

Make the arrays of Lists into Lists of Lists and see what happens. That's the only thing that looks strange in the constructor to me.

Show more comments

1 Reply

· Add your reply
  • Sort: 
avatar image

Answer by demonpants · Jan 27, 2013 at 01:01 AM

Yup, the JIT error is for sure caused by those multidimensional arrays. I had the same issue with my game. You could probably fix it by using non-dynamic arrays (int[][][][]) but as a Java guy I was annoyed with how those are treated. Also, when you're doing so many dimensions (like 8), you probably want to flatten everything into a 1D array for better performance. I made a quick class for doing this.

 using System.Collections;
 
 //this focuses on speed, not safety, so don't call a function that
 //uses a length bigger than what you passed in
 public class FlattenedFloatArray
 {
     private float[] array;
     private int[] dimensionMultiples;
     private int[] dimensionLengths;
     private int totalLength;
     
     public FlattenedFloatArray( int[] dimensions )
     {
         dimensionLengths = dimensions;
         
         totalLength = 1;
         for ( int i = 0; i < dimensions.Length; i++ )
         {
             totalLength *= dimensions[i];
         }
         array = new float[ totalLength ];
         
         dimensionMultiples = new int[ dimensions.Length ];
         dimensionMultiples[ dimensions.Length - 1 ] = 1;
         for ( int i = dimensions.Length - 2; i >= 0; i-- )
         {
             dimensionMultiples[i] = dimensions[i+1] * dimensionMultiples[i+1];
         }
     }
     
     public float Get( int i, int j )
     {
         return array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] ];
     }
     
     public float Get( int i, int j, int k )
     {
         return array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] + k * dimensionMultiples[2] ];
     }
     
     public float Get( int i, int j, int k, int l )
     {
         return array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] + k * dimensionMultiples[2] + l * dimensionMultiples[3] ];
     }
     
     public float Get( int i, int j, int k, int l, int m )
     {
         return array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] + k * dimensionMultiples[2] + l * dimensionMultiples[3] + m * dimensionMultiples[4] ];
     }
     
     public float Get( int[] indices )
     {
         int index = 0;
         for ( int i = 0; i < indices.Length; i++ )
         {
             index += indices[i] * dimensionMultiples[i];
         }
         return array[ index ];
     }
     
     public void Set( float v, int i, int j )
     {
         array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] ] = v;
     }
     
     public void Set( float v, int i, int j, int k )
     {
         array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] + k * dimensionMultiples[2] ] = v;
     }
     
     public void Set( float v, int i, int j, int k, int l )
     {
         array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] + k * dimensionMultiples[2] + l * dimensionMultiples[3] ] = v;
     }
     
     public void Set( float v, int i, int j, int k, int l, int m )
     {
         array[ i * dimensionMultiples[0] + j * dimensionMultiples[1] + k * dimensionMultiples[2] + l * dimensionMultiples[3] + m * dimensionMultiples[4] ] = v;
     }
     
     public void Set( float v, int[] indices )
     {
         int index = 0;
         for ( int i = 0; i < indices.Length; i++ )
         {
             index += indices[i] * dimensionMultiples[i];
         }
         array[ index ] = v;
     }
     
     public int GetTotalLength()
     {
         return array.Length;
     }
     
     public int GetDimensionCount()
     {
         return dimensionMultiples.Length;
     }
     
     public int GetLength( int dimension )
     {
         return dimensionLengths[ dimension ];
     }
 }
Comment
whydoidoit

People who like this

1 Show 0 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

ios: 2 function calls on the same interface, one working... the other function call doing literally nothing 0 Answers

AWS in iOS not working 2 Answers

Ads Showing Only in Editor 0 Answers

how to iPhone X home button hide or disable ? 0 Answers

How to solve ITMS-90809: Deprecated API Usage? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges