C# 读取大型JSON文件而不挂起Unity

C# 读取大型JSON文件而不挂起Unity,c#,json,unity3d,C#,Json,Unity3d,我正在开发一款手机游戏,需要加载一个约17MB的4D 60X40X60X40整数数组。我目前正在读取JSON中的数据,并使用SimpleJSON.cs在Unity中进行反序列化 使用SimpleJSON解析字符串时会出现问题。游戏挂起,加载文件大约需要30秒 我尝试过使用ijob,但它们不允许使用字符串(不可blittable) 主要优先考虑的是悬挂部分。它不允许我在用户等待加载JSON时向他们提供反馈。当然,降低加载时间和任何提示都会非常有用 我的代码: IEnumerator StartLo

我正在开发一款手机游戏,需要加载一个约17MB的4D 60X40X60X40整数数组。我目前正在读取JSON中的数据,并使用SimpleJSON.cs在Unity中进行反序列化

使用SimpleJSON解析字符串时会出现问题。游戏挂起,加载文件大约需要30秒

我尝试过使用ijob,但它们不允许使用字符串(不可blittable)

主要优先考虑的是悬挂部分。它不允许我在用户等待加载JSON时向他们提供反馈。当然,降低加载时间和任何提示都会非常有用

我的代码:

IEnumerator StartLoadFiles()
{
    // Wait to give time for the game to load everything else
    yield return new WaitForSeconds(1f);

    /// First read the transition matrices. We are using TextAsset
    /// because of compatibility issues with Android.
    TextAsset file;
    yield return file = Resources.Load(transitionPath) as TextAsset;

    loadingSlider.value = 0.3f;
    string transitionString = file.ToString();
    loadingSlider.value = 0.5f;

    /// We are using SimpleJSON.cs as of now. Maybe there is
    /// something faster out there... (Here is where it hangs)
    JSONNode N;
    yield return N = JSON.Parse(transitionString);

    loadingSlider.value = 0.7f;
}

编辑:我已经在使用一个没有区别的协同程序。

请注意,协同程序本身是非异步的!在
更新
之后,它仍然在Unity主线程中运行
IEnumerator
的每次迭代

您更愿意使用任务/线程,例如(假设文本资源加载的第一部分按预期工作)

private int[,,]loadValues=null;
IEnumerator加载文件()
{
//等待游戏加载其他内容的时间
返回新的等待秒(1f);
文本资产文件;
收益返回文件=Resources.Load(transitionPath)作为TextAsset;
载荷滑动器。值=0.3f;
string transitionString=file.ToString();
荷载滑道值=0.5f;
//不知何故,您必须等待回调到主线程
//最简单的方法是线程安全队列
var actions=new ConcurrentQueue();
//现在启动线程并等待结果
var-thread=新线程(()=>加载线程(操作));
thread.Start();
while(loadValues==null)
{
//处理maint线程中的操作
while(actions.Count>0&&actions.TryDequeue(out-var-action)
{
action?.Invoke();
}  
收益返回空;
} 
Debug.Log(“已完成加载”);
//现在用“loadValues”
}
私有void加载线程(ConcurrentQueue操作)
{
尝试
{
var N=JSON.Parse(transitionString);
actions.Enqueue(()=>{loadingSlider.value=0.7f;});
var输出=新整数[60,40,60,40];
对于(变量x=0;x<60;x++)
{
对于(变量y=0;y<40;y++)
{
对于(var z=0;z<60;z++)
{
对于(var w=0;w<40;w++)
{
//当然,这取决于您的json格式
输出[x,y,z,w]=N[x][y][z][w];
}
}
}
}  
actions.Enqueue(()=>{
载荷值=输出;
荷载滑道值=1f;
});
}
捕获(例外e)
{
LogException(e);
Enqueue(()=>{loadValues=newint[0,0,0];});
}
}


注意:在智能手机上输入,但我希望想法变得清晰

您可以尝试。我不确定这是否能在四维数组中有效工作,但如果这能提高您的性能,您可以将您的4D数组分离为4片1D数组。此外,您可以使用Json.net,它支持直接从流进行反序列化。您是一个真正的上帝和我都配不上你。太感谢你了!它就像一个魔咒,甚至让加载速度快了近20%。有什么建议可以让加载速度更快吗?@VaggelisStamkopoulos没有我也不^^^好
资源。加载
文本资产。如果你的文件那么大,ToString
是相当昂贵的。所以如果有poss的话可以通过直接文件在线程中完全异步加载它们,而不是使用它!实际上,如果有其他方法;)例如,将文件放在
流化资产中,并使用流式反序列化。。这样,您甚至不必首先将整个内容加载到内存中
private int[,,,] loadValues = null;


IEnumerator StartLoadFiles()
{
    // Wait to give time for the game to load everything else
    yield return new WaitForSeconds(1f);

    TextAsset file;
    yield return file = Resources.Load(transitionPath) as TextAsset;

    loadingSlider.value = 0.3f;
    string transitionString = file.ToString();
    loadingSlider.value = 0.5f;

    // Somehow you have to wait for callbacks into the main thread
    // simplest way is a thread-safe Queue
    var actions = new ConcurrentQueue<Action>();

    // Now start the thread and wait for results
    var thread = new Thread(() => LoadingThread(actions));
    thread.Start();

    while(loadValues == null)
    {
        // process the actions in the maint hread 
        while(actions.Count > 0 && actions.TryDequeue(out var action)
        {
            action?.Invoke();
        }  

        yield return null;
    } 

    Debug.Log("Finished loading");

    // Now o something with "loadValues"
}

private void LoadingThread(ConcurrentQueue actions)
{
    try
    {
        var N = JSON.Parse(transitionString);

        actions.Enqueue(() => {loadingSlider.value = 0.7f;});

        var output = new int[60,40,60,40];

        for(var x = 0; x < 60; x++)
        {
            for(var y = 0; y < 40; y++)
            {
                for(var z = 0; z < 60; z++)
                {
                    for(var w = 0; w < 40; w++)
                    {
                        // Depending on your json format of course
                        output[x,y,z,w] = N[x][y][z][w];
                    }
                }
            }
        }  

        actions.Enqueue(() => {
            loadValues = output;
            loadingSlider.value = 1f;
        });
    }
    catch(Exception e)
    {
        Debug.LogException(e);
        actions.Enqueue(() => {loadValues = new int[0,0,0,0];});
    }
}