【问题标题】:How to refresh Unity at run time?如何在运行时刷新 Unity?
【发布时间】:2018-03-23 08:58:05
【问题描述】:

在上面的短片中,您将看到我在 Unity 中的设置相当少。有一个计数器每帧递增(在更新中),旁边就是这个调用“UnityEditor.SceneView.RepaintAll()”。您可以看到正在输出到控制台框的计数器。

一旦我进入游戏视图并单击左下角的一个按钮(按下突出显示的按钮),它会调用一个脚本,该脚本在运行时将网格导入场景并渲染它。您会注意到在此期间计数器和重绘调用冻结,尽管时间很短,但非常明显。实际上,在这个加载时间内,场景中的所有内容都会冻结。

我一直在谷歌上搜索如何刷新 Unity 的场景,这样我就可以在运行时加载网格,同时保持对玩家的响应能力。到目前为止,什么都没有。

这里定期刷新/更新场景以使玩家不受加载时间游戏暂停的影响的最佳做法是什么?

编辑:RepaintAll() 调用对我不起作用。之前应该添加的。这种方法并没有像我希望的那样起作用,实际上我不确定如果不刷新场景它的目的是什么

网格导入代码:

    const int MAX_FACETS_PER_MESH = 65535 / 3;

    class Facet
    {
        public Vector3 normal;
        public Vector3 a, b, c;

        public override string ToString()
        {
            return string.Format("{0:F2}: {1:F2}, {2:F2}, {3:F2}", normal, a, b, c);
        }
    }

    private static Mesh[] ImportBinary(string path)
    {
        Facet[] facets;

        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()))
            {
                // read header
                byte[] header = br.ReadBytes(80);
                uint facetCount = br.ReadUInt32();
                facets = new Facet[facetCount];

                for(uint i = 0; i < facetCount; i++)
                {
                    facets[i] = new Facet();

                    facets[i].normal.x = br.ReadSingle();
                    facets[i].normal.y = br.ReadSingle();
                    facets[i].normal.z = br.ReadSingle();

                    facets[i].a.x = br.ReadSingle();
                    facets[i].a.y = br.ReadSingle();
                    facets[i].a.z = br.ReadSingle();

                    facets[i].b.x = br.ReadSingle();
                    facets[i].b.y = br.ReadSingle();
                    facets[i].b.z = br.ReadSingle();

                    facets[i].c.x = br.ReadSingle();
                    facets[i].c.y = br.ReadSingle();
                    facets[i].c.z = br.ReadSingle();

                    // padding
                    br.ReadUInt16();
                }
            }
        }

        return CreateMeshWithFacets(facets);
    }

    private static Mesh[] CreateMeshWithFacets(IList<Facet> facets)
    {
        int fl = facets.Count, f = 0, mvc = MAX_FACETS_PER_MESH * 3;
        Mesh[] meshes = new Mesh[fl / MAX_FACETS_PER_MESH + 1];

        for(int i = 0; i < meshes.Length; i++)
        {
            int len = System.Math.Min(mvc, (fl - f) * 3);
            Vector3[] v = new Vector3[len];
            Vector3[] n = new Vector3[len];
            int[] t = new int[len];

            for(int it = 0; it < len; it += 3)
            {
                v[it  ] = facets[f].a;
                v[it+1] = facets[f].b;
                v[it+2] = facets[f].c;

                n[it  ] = facets[f].normal;
                n[it+1] = facets[f].normal;
                n[it+2] = facets[f].normal;

                t[it  ] = it;
                t[it+1] = it+1;
                t[it+2] = it+2;

                f++;
            }

            meshes[i] = new Mesh();
            meshes[i].vertices = v;
            meshes[i].normals = n;
            meshes[i].triangles = t;
        }

        return meshes;
    }

【问题讨论】:

  • 请参阅this 帖子了解如何使用 ThreadPool 和我编写的 UnityThread 类来做到这一点
  • @Programmer “[One] 可以启动一个单独的线程......只要它们不调用在该线程中执行的任何 Unity 函数”,从您的链接中引用“lockstock”。我想使用 Mesh 构造函数的导入代码(见上文)意味着它不能在新线程中运行。
  • @lockstock 是这样吗?
  • 是的,你不能在另一个线程中使用 Unity 的 API。很少有例外。其中之一是Vector3 类。您可以在其他课程中使用它。我认为您不能使用 Mesh 类,但请尝试一下。如果它显示错误,那么你不能。冻结的代码部分是您正在使用 FileStream 读取文件的部分。在另一个线程中执行此操作。
  • @Programmer 不完全确定这是可能的。您的意思是将using 两个语句FileStreamBinaryReader 分开,并在FS 之外使用BR?看不到这将如何提高整体性能。 FS 线程需要在将其数据发送到 BR 之前完全完成,不是吗?请澄清

标签: c# unity3d


【解决方案1】:

您正在尝试同步执行文件 IO,这会锁定它正在运行的任何线程。在这种情况下,主线程。

您可以在剪辑的所有三个区域看到此锁定的效果:

  • 场景视图不更新
  • 游戏视图不更新
  • 控制台停止记录

这是因为 Update() 根本没有运行。

为了解决这个问题,您需要异步加载文件。

【讨论】:

  • 解释得很好,谢谢 Draco。那么这里的修复是否像使这些函数异步一样简单?
  • @jtth 你必须对它做一些研究。我没有异步完成任何 System.FileIO 的事情,只有统一的事情(例如资源)。我粗略地搜索了一下,但只找到了我已经知道的东西。
  • 没有使用(非常简单但非常出色的)TPL 任务,我认为 Unity 的 .Net 3.5 运行时不提供这些任务,您将不得不使用单独的线程来进行如此繁重的计算。但是,请记住,线程在 WSA 应用程序中不可用。
猜你喜欢
  • 1970-01-01
  • 2013-09-16
  • 2014-01-08
  • 2021-07-14
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多