NodeCanvas Forums › Support › [NC2] AoT iOS Jit Error on Startup › Reply To: [NC2] AoT iOS Jit Error on Startup
Ok! We’ve got it fully working on PS4 now. I think…
After making the modifications to fsMetaProperty
I listed above, we noticed that AnimationCurves were not deserializing properly, and somehow showed up with completely blank Keyframes. Since Keyframes are structs (and are therefore passed by value), fsMetaProperty.Write
wasn’t modifying the Keyframes that would eventually be passed back to the AnimationCurves. The same thing was probably happening to Rects, but we didn’t notice because we don’t use Rects in our Graphs (except for layout, of course).
Our solution was to force pass-by-reference the context object into fsMetaProperty.Write
using the ref
keyword and then reassign the modified struct to that reference at the end. So, our final, working version of fsMetaProperty.Write
looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
public void Write(ref object context, object value) { var field = _memberInfo as FieldInfo; var property = _memberInfo as PropertyInfo; if (field != null) { field.SetValue(context, value); } // TODO: Find general value-type setter else if (context is UnityEngine.Rect) { UnityEngine.Rect r = (UnityEngine.Rect)context; switch (_memberInfo.Name) { case "xMin": r.xMin = (float)value; break; case "yMin": r.yMin = (float)value; break; case "xMax": r.xMax = (float)value; break; case "yMax": r.yMax = (float)value; break; } context = r; } else if (context is UnityEngine.Keyframe) { UnityEngine.Keyframe a = (UnityEngine.Keyframe)context; switch (_memberInfo.Name) { case "inTangent": a.inTangent = (float)value; break; case "outTangent": a.outTangent = (float)value; break; case "tangentMode": a.tangentMode = (int)value; break; case "time": a.time = (float)value; break; case "value": a.value = (float)value; break; } context = a; } else if (property != null) { var setMethod = property.GetSetMethod(/*nonPublic:*/ true); if (setMethod != null) { try { setMethod.Invoke(context, new object[] { value }); } catch (Exception e) { UnityEngine.Debug.LogError("|||||||||||||||||||||||||||||||||||||||"); UnityEngine.Debug.LogError("Error writing property. Is this a a value-type?"); UnityEngine.Debug.LogError(context); UnityEngine.Debug.LogError(setMethod.Name); UnityEngine.Debug.LogError(_memberInfo.Name); UnityEngine.Debug.LogError(value); UnityEngine.Debug.LogError(e); UnityEngine.Debug.LogError("|||||||||||||||||||||||||||||||||||||||"); throw e; } } } } |
Obviously, this is not the perfect solution. If we ever introduce new structs to NodeCanvas, we’ll likely have to update this function again. I also fear that we will have to update fsMetaProperty.Read
if we ever introduce anything containing a struct to NodeCanvas. However, this works, and seeing as we have a deadline rapidly approaching, we’re going to roll with this fix for the time being.
Finally, we ran into a strange hard crash on our dev kits containing the error message Ran out of trampolines of type 2
. Turns out trampolines are artifacts within Mono that are used in dealing with generics. Since NC2 by-and-large relies on generics more, you may run into this error. To fix it, go to your Player Settings, and under Other Settings, update AOT Compilation Options with nimt-trampolines=512
. Trampolines ostensibly incur a memory cost, but I honestly haven’t researched it enough to know how many trampolines is too much, resource-wise.
So, complete (janky) solution:
fsMetaProperty.Write
to include an explicit setter for each of the properties on that structfsMetaProperty.Read
to include an explicit getter for each of the fields on that objectHope that helps!