正常写Arcade-Chan,本已经发布了v3.0.0 Beta 3,结果官群里大量用户反馈加载谱面时报错
Attempting to call method 'System.Linq.Expressions.Interpreter.LightLambda::MakeRun2<System.Runtime.CompilerServices.CallSite,System.Object,System.Boolean>' for which no ahead of time (AOT) code was generated.
一开始以为是Jint的问题,因为Beta 2没有Jint存在(脚本系统是Beta 3才加的),而且Jint是动态执行JS的,刚好可能不太适合IL2CPP AOT环境。
结果把Jint代码删了,甚至把LoadScript()
都注释掉仍然报错。
想了下是不是因为IL2CPP把那个报错的程序集给裁掉了,结果link.xml里写的满当当的保存再生成还是报错。
大概一个小时后,注意到了报错提示的对话框顶部写的是谱面读取错误
,于是就猜测“是不是谱面文件解析里哪里用到动态的抛出了异常”
把堆栈信息拿到后,很快就锁定了这段代码:
dynamic dyTrack;
try
{
dyTrack = CheckValueType<RawAffInt>(context.values().value()[2], "tap", ArcadeI18NManager.GetCurrentLangHardCodingData("Compose.Aff").Value<string>("Universal.Track"),
warningAsException: true); // 将警告视为错误以使其按照int解析失败抛出异常后再尝试按照float解析
}
catch
{
// ftv(floating track value)
dyTrack = CheckValueType<RawAffFloat>(context.values().value()[2], "tap", ArcadeI18NManager.GetCurrentLangHardCodingData("Compose.Aff").Value<string>("Universal.Track"));
}
心想着是不是IL2CPP dynamic
的问题,一开始想改成object dyTrack
,后来想了下这太无视类型了,就改成了RawAffInt
和RawAffFloat
都继承自的IRawAffValue
,也就是:
IRawAffValue dyTrack;
try
{
dyTrack = CheckValueType<RawAffInt>(context.values().value()[2], "tap", ArcadeI18NManager.GetCurrentLangHardCodingData("Compose.Aff").Value<string>("Universal.Track"),
warningAsException: true); // 将警告视为错误以使其按照int解析失败抛出异常后再尝试按照float解析
}
catch
{
// ftv(floating track value)
dyTrack = CheckValueType<RawAffFloat>(context.values().value()[2], "tap", ArcadeI18NManager.GetCurrentLangHardCodingData("Compose.Aff").Value<string>("Universal.Track"));
}
重新打包,再加载谱面,仍然出现同样的错误,但堆栈变了(从GenTap()
变成了GenHold()
):
于是就想既然之前为了添加浮点轨道值支持而给Tap加了这段代码,由于Hold也是地面音符,会不会也有类似的问题。
果不其然:
dynamic dyTrack;
try
{
dyTrack = CheckValueType<RawAffInt>(context.values().value()[2], "hold", ArcadeI18NManager.GetCurrentLangHardCodingData("Compose.Aff").Value<string>("Universal.Track"),
warningAsException: true); // 将警告视为错误以使其按照int解析失败抛出异常后再尝试按照float解析
}
catch
{
// ftv(floating track value)
dyTrack = CheckValueType<RawAffFloat>(context.values().value()[2], "hold", ArcadeI18NManager.GetCurrentLangHardCodingData("Compose.Aff").Value<string>("Universal.Track"));
}
与GenTap()
方法的处理方式一样,改成IRawAffValue dyTrack;
后重新打包,再次加载谱面,问题解决。
看起来IL2CPP不太支持dynamic
类型呢……以后再遇到使用dynamic
的情况用object
替换算了。