我一直在读关于NativeArray的文章,但我不得不承认我不理解它。
从文件中:
NativeArray将本机内存的缓冲区公开给托管代码,这样就可以在托管和本机之间共享数据而不需要编组成本。
我必须承认,我对这里所说的话一窍不通。
使用它代替普通数组或列表有什么意义?有人能给我举一个如何使用它的例子,以及如何不使用它吗?
发布于 2019-08-26 15:16:12
相当新的统一作业系统 利用本机阵列 (以及他们的新表兄弟NativeList
,NativeHashMap
,NativeMultiHashMap
和NativeQueue
)。作业系统允许您在多个CPU核上分发昂贵的游戏计算。它还允许您使用突发编译代码,这比普通代码要快得多.但代价是,突发代码不能使用大多数默认的C#功能。本机容器族是常规C#容器类的替代品。
本机容器主要用于在作业和“常规”游戏代码之间共享数据。整个系统和它改变的方式,您的结构代码的统一游戏是相当复杂的解释,只是在一个单一的答案范围内。我推荐这个统一GDC谈话作为对它的介绍。
本机数组也与本机插件通信相关。本机插件是从可以用任何编程语言编写的代码中编译的DLL文件,包括“不安全”的编程语言(如C++ ),它允许您通过省略一些常识的安全检查来编写非常快的代码。使用本机数组时,统一代码和DLL代码都可以对相同的数据进行操作。否则,您需要来回复制每个函数调用的整个数组,这可能是非常慢的,以至于它否定了您希望首先使用本机插件获得的性能增益。示例:
// importing the function UpdateArray from myLibrary.DLL
// The function expects a memory location ("pointer") where an array of bytes can be found.
[DllImport("myLibrary")]
unsafe public static extern void UpdateArray(void* bytes);
// declaring a native array used for communication with the DLL
private NativeArray<byte> nativeByteArray;
// call the function from the DLL each update while passing the array by reference instead of by value
void Update() {
unsafe {
void* ptr = NativeArrayUnsafeUtility.GetUnsafePtr(nativeByteArray);
UpdateArray(ptr);
}
}
在过去的几年中,本机插件失去了很多相关性,因为性能优化、特性添加和第三方资产使得它们在许多用例中变得不必要。此外,本机插件必须为每个平台单独编译,并不是每项技术都能使交叉编译像团结一样容易。因此,他们可以成为创造一个跨平台游戏的额外障碍。
但是,对于一些不太常见的场景,比如与非标准硬件的接口,它们仍然是有用的。
发布于 2019-08-26 15:34:29
我不是原生代码方面的专家,所以我不会在这里详细介绍,但我仍然认为我可以给你足够的信息来回答这个问题。
如果您愿意的话,可以在任何地方使用NativeArray,但是主要是在联合的作业系统中使用。而且他们的ecs系统(或圆点)也在使用它(在写作的时候,dots仍在预览中,就像在beta版中一样)。
统一的工作系统是快速和安全的多线程。我的意思是,他们做了很多检查,并添加了一些限制,以确保您在编写多线程代码时不会得到一些常见错误,因为体系结构根本不允许您这样做。
这些限制说明了这样一个事实:例如,不允许在作业中引用类(仅限于结构)。这很好,因为这意味着您不能在同时运行的2个作业中修改相同的值,您不能意外地这样做,因为每个作业都得到该值的副本,这意味着两个作业永远不会在内存中得到相同的值。另一方面,这也意味着由于同样的原因,两个作业在彼此之后运行不能修改相同的值。
见见NativeContainers。它们是指向一段本机内存的结构,这意味着它们可以在作业系统中使用,如果两个作业在彼此之后运行,它们仍然可以访问相同的(本机)内存。然后团结起来,围绕着这些NativeContainers建立他们的安全体系。例如,如果您确实尝试从两个不同的作业(可以同时运行)写入NativeContainer中的同一个内存,那么统一会抛出错误,告诉您不允许这样做,并且应该确保其中一个作业依赖于另一个作业先完成。
另一个优点是,由于Unity强制您进入一个具有许多限制(包括使用NativeCollections )的特定模式,所以在启用Burst编译器时,团结可以为您优化许多事情。这意味着您可以编写高性能的C#代码。这可能是一个巨大的差异(取决于场景)。
然而,有一些规则适用于NativeArrays。这些规则基本上是为了确保正确使用NativeArray。
您可以找到有关安全系统这里的更多背景信息。
至于何时使用它:
如果您不使用作业系统(或者dots,因为它也使用作业系统),我个人不会建议您使用它,因为在常规的Unity中使用时,性能上的差异甚至可能是不明显的,而缺点仍然存在。但是不要相信我的话,自己检查以确保(在构建中,统一在编辑器中做了很多额外的检查,使它慢下来)
如果您正在使用作业系统,您应该使用它们,因为您不能使用作业内部的常规数组。
没有必要向您展示如何在作业系统之外使用NaiveArray (也许其他插件已经在另一个答案中完成),并且给出一个作业系统的示例需要我解释很多属于这个答案范围之外的作业系统本身。因此,我建议你去看看这里的例子,或者搜索有关统一工作系统的例子。
https://gamedev.stackexchange.com/questions/174953
复制相似问题