正常写Arcade-Chan,本已经发布了v3.0.0 Beta 3,结果官群里大量用户反馈加载谱面时报错
受害者1
受害者2-1
受害者2-2
受害者2-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,后来想了下这太无视类型了,就改成了RawAffIntRawAffFloat都继承自的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替换算了。

Last modification:September 29, 2023
如果觉得我的文章对你有用,请随意赞赏