ArithmeticException:函数不接受浮点非数字值 PointwiseSign() 在 Unity WebGL 中不起作用

问题描述

我在 Unity 中有一个函数,它目前在 Unity 编辑器和 Windows 版本中有效,但在 WebGL 版本中无效。在浏览器中,我收到以下错误

  at System.Math.Sign (System.Double value) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Double.Vector+<>c.<DoPointwiseSign>b__31_0 (System.Double x) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Func`2[T,TResult].Invoke (T arg) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Storage.DenseVectorStorage`1+<>c__displayClass30_0`1[T,TU].<MapToUnchecked>b__0 (system.int32 a,system.int32 b) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Action`2[T1,T2].Invoke (T1 arg1,T2 arg2) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Threading.CommonParallel.For (system.int32 fromInclusive,system.int32 toExclusive,system.int32 rangeSize,System.Action`2[T1,T2] body) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Storage.DenseVectorStorage`1[T].MapToUnchecked[TU] (MathNet.Numerics.Linearalgebra.Storage.VectorStorage`1[T] target,System.Func`2[T,TResult] f,MathNet.Numerics.Linearalgebra.Zeros zeros,MathNet.Numerics.Linearalgebra.ExistingData existingData) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Storage.VectorStorage`1[T].MapTo[TU] (MathNet.Numerics.Linearalgebra.Storage.VectorStorage`1[T] target,MathNet.Numerics.Linearalgebra.ExistingData existingData) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Vector`1[T].Map (System.Func`2[T,MathNet.Numerics.Linearalgebra.Vector`1[T] result,MathNet.Numerics.Linearalgebra.Zeros zeros) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Double.Vector.DoPointwiseSign (MathNet.Numerics.Linearalgebra.Vector`1[T] result) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Action`1[T].Invoke (T obj) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Vector`1[T].PointwiseUnary (System.Action`1[T] f) [0x00000] in <00000000000000000000000000000000>:0 
  at MathNet.Numerics.Linearalgebra.Vector`1[T].PointwiseSign () [0x00000] in <00000000000000000000000000000000>:0 
  at EBM.Integrate (MathNet.Numerics.Linearalgebra.Vector`1[T] T,system.int32 years,system.int32 timesteps) [0x00000] in <00000000000000000000000000000000>:0 
  at EBM.Calc (System.Collections.Generic.IEnumerable`1[T] input,system.int32 timesteps) [0x00000] in <00000000000000000000000000000000>:0 
  at World.Calc (System.Boolean useTemp,system.int32 steps) [0x00000] in <00000000000000000000000000000000>:0 
  at World.Init () [0x00000] in <00000000000000000000000000000000>:0 
  at GameManager.Awake () [0x00000] in <00000000000000000000000000000000>:0 
 
(Filename: currently not available on il2cpp Line: -1)

导致错误函数是此处的 Integrate() 函数

/// <summary> Does entire timestep integration calculation </summary>
    public static (Matrix<double>,Matrix<double>) Integrate(Vector<double> T = null,int years = 0,int timesteps = 0)
    {
        T = T ?? 7.5f + 20 * (1 - 2 * x.PointwisePower(2));
        years = years == 0 ? dur : years;
        timesteps = timesteps == 0 ? nt : timesteps;
        Matrix<double> Tfin = Matrix<double>.Build.Dense(bands,nt,0);
        Matrix<double> Efin = Matrix<double>.Build.Dense(bands,0);
        Matrix<double> T0fin = Matrix<double>.Build.Dense(bands,0);
        Matrix<double> ASRfin = Matrix<double>.Build.Dense(bands,0);
        
        //Matrix<double> tfin = Matrix<double>.Build.Dense()np.linspace(0,1,nt);
        Vector<double> Tg = Vector<double>.Build.DenSEOfVector(T);
        Vector<double> E = Tg * cw;
        
        for (var (i,p) = (0,0); i < years; i++)
        {
            for (int j = 0; j < timesteps; j++)
            {
                /*              if (j % (nt / 100f) == 0)
                                {
                                    Efin.SetColumn(p,E);
                                    Tfin.SetColumn(p,T);
                                    p++;
                                }*/
                Vector<double> alpha = E.PointwiseSign().PointwiseMultiply(aw).Map(x => x < 0 ? aI : x); // aw * (E > 0) + ai * (E < 0)
                Vector<double> C = alpha.PointwiseMultiply(S.Row(j)) + cg_tau * Tg - A + F; // alpha * S[i,:] + cg_tau * Tg - A
                Vector<double> T0 = C / (M - k * Lf / E);

                if (i == dur - 1)
                {
                    Efin.SetColumn(j,E);// [":",i] = E;
                    Tfin.SetColumn(j,T);//[":",i] = T;
                    T0fin.SetColumn(j,T0);//[":",i] = T0;
                    ASRfin.SetColumn(j,alpha.PointwiseMultiply(S.Row(j)));//[":",i] = alpha * S[i,":"];
                }

                T = Sign0(GreatOrE,E) / cw + Sign0(Less,Sign0(Less,E,T0)); // E/cw*(E >= 0)+T0*(E < 0)*(T0 < 0)
                E = E + dt * (C - M * T + Fb);
                var mklfe = M - k * Lf / E;
                var signlesset0 = Sign0(Less,T0);

                /*# Implicit Euler on Tg
                # latent heat transport
                # n.b. this is semi-implicit,with some derivatives are
                # calculated on the prevIoUs time steP*/
                var q = RH * saturation_specific_humidity(Tg,Ps);
                var rhs1 = (dt * diffop / cg) * (Lv * q / cp);
                Tg = (kappa - Matrix<double>.Build.DiagonalOfDiagonalVector(
                    Sign0(Less,signlesset0,dc / mklfe) // np.diag(dc / (M - kLf / E) * (T0 < 0) * (E < 0)
                )).solve(Tg + rhs1 + dt_tau * (
                    Sign0(GreatOrE,E) / cw + (aI * S.Row(j) - A + F). // E / cw * (E >= 0) + (ai * S[i,:] - A)
                    Map2((a,b) => b != 0 ? a / b : 0,// funky division
                        Sign0(Less,mklfe)) // (M - kLf / E) * (T0 < 0) * (E < 0)
                ));
            }
        }

根据堆栈跟踪,问题似乎出在行 Vector<double> alpha = E.PointwiseSign().PointwiseMultiply(aw).Map(x => x < 0 ? aI : x);

我不明白的是为什么代码在游戏的其他版本中有效,但在 WebGL 版本中却中断了。任何帮助将不胜感激。

解决方法

想出了一种解决方案——出于某种原因,这在 Unity 2019.3 中随机中断,但升级到 2019.4,现在该功能似乎一直在工作。可能与不同版本如何将函数转换为 WebGL 有关系。