在为公司的Unity3d游戏从Mono迁移到IOS 64过程中,出现了许多问题。
在看到Xcode提示Build Success时会有一种成就感油然而生,但是噩梦才刚刚开始。
由于IL2CPP的不完善或者说这种把C#代码转换成C++的方式太粗暴,不仅在Build阶段会出现很多错误,在运行期出现的异常崩溃更是数不胜数。
解决掉Build阶段的错误之后,昨天终于把游戏运行起来,但是在进入主城之后就黑屏了,What Fuck!
不过还好在Xcode中有异常爆出。
Method not found: 'Default constructor not found...ctor() of System.ComponentModel.Int64Converter'. at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <filename unknown>:0 at System.ComponentModel.TypeDescriptor.GetConverter (System.Type type) [0x00000] in <filename unknown>:0 at Pathfinding.Serialization.JsonFx.TypeCoercionUtility.CoerceType (System.Type targetType, System.Object value) [0x00000] in <filename unknown>:0 at Pathfinding.Serialization.JsonFx.JsonReader.ReadNumber (System.Type expectedType) [0x00000] in <filename unknown>:0 at Pathfinding.Serialization.JsonFx.JsonReader.Read (System.Type expectedType, Boolean typeIsHint) [0x00000] in <filename unknown>:0 at Pathfinding.Serialization.JsonFx.JsonReader.PopulateObject (System.Object& result, System.Type objectType, System.Collections.Generic.Dictionary`2 memberMap, System.Type genericDictionaryType) [0x00000] in <filename unknown>:0
什么鬼。
但是根据异常来看,异常指向了系统函数……
没办法只有谷歌。
在Unity官方论坛终于看到有开发者反应这个问题,怀疑是因为Unity的代码裁剪优化,消减了这一部分的代码支持!
官方技术支持回答说,不大可能是这个优化造成的,但是也还是给出了一个解决方案。
对于提示出异常的类,创建一个脚本,在这个脚本里面使用new 来调用一下这个类的构造函数,这样就避免被优化裁剪。
I actually doubt this is a stripping issue. It is more likely related to an AOT limitation. IL2CPP can only construct and instance of a type at runtime that it knows about at compile time. So for a call to System.Activator.CreateInstance to succeed, IL2CPP needs to have previously generated code for the System.Type passed as the first argument to CreateInstance. You may be able to work around this issue by declaring an unused field of type System.ComponentModel.Int64Converter in a class that will not be stripped. A MonoBehaviour in one of your scripts is likely a good candidate. Maybe try something like this:
class AotTypes : MonoBehaviour { private static System.ComponentModel.Int64Converter _unused = new System.ComponentModel.Int64Converter(); }
private static System.ComponentModel.Int64Converter _unused = new System.ComponentModel.Int64Converter(); private static System.ComponentModel.DecimalConverter _unused2 = new System.ComponentModel.DecimalConverter(); private static System.ComponentModel.ByteConverter _unused3 = new System.ComponentModel.ByteConverter(); private static System.ComponentModel.CollectionConverter _unused4 = new System.ComponentModel.CollectionConverter(); private static System.ComponentModel.CharConverter _unused5 = new System.ComponentModel.CharConverter(); private static System.ComponentModel.SByteConverter _unused6 = new System.ComponentModel.SByteConverter(); private static System.ComponentModel.Int16Converter _unused7 = new System.ComponentModel.Int16Converter(); private static System.ComponentModel.UInt16Converter _unused8 = new System.ComponentModel.UInt16Converter(); private static System.ComponentModel.Int32Converter _unused9 = new System.ComponentModel.Int32Converter(); private static System.ComponentModel.UInt32Converter _unused10 = new System.ComponentModel.UInt32Converter(); private static System.ComponentModel.Int64Converter _unused11 = new System.ComponentModel.Int64Converter(); private static System.ComponentModel.UInt64Converter _unused12 = new System.ComponentModel.UInt64Converter(); private static System.ComponentModel.DoubleConverter _unused13 = new System.ComponentModel.DoubleConverter(); private static System.ComponentModel.SingleConverter _unused14 = new System.ComponentModel.SingleConverter(); private static System.ComponentModel.BooleanConverter _unused15 = new System.ComponentModel.BooleanConverter(); private static System.ComponentModel.StringConverter _unused16 = new System.ComponentModel.StringConverter(); private static System.ComponentModel.DateTimeConverter _unused17 = new System.ComponentModel.DateTimeConverter(); private static System.ComponentModel.EnumConverter _unused18 = new System.ComponentModel.EnumConverter(typeof(<any your enum>)); private static System.ComponentModel.TimeSpanConverter _unused19 = new System.ComponentModel.TimeSpanConverter();
游戏成功运行。