安全系统复制数据的过程的缺点是会将作业的结果隔离到每个副本中。为了克服此限制,需要将结果存储在一种名为 NativeContainer 的共享内存中。
A NativeContainer
is a managed value type that provides a safe C# wrapper for native memory. It contains a pointer to an unmanaged allocation. When used with the Unity C# Job System, a NativeContainer
allows a job to access data shared with the main thread rather than working with a copy.
Unity 附带了一个名为 NativeArray 的 NativeContainer
。您也可以使用 NativeSlice 操作 NativeArray
,从特定位置获取特定长度的 NativeArray
子集。
Note: The Entity Component System (ECS) package extends the Unity.Collections
namespace to include other types of NativeContainer
:
NativeList
- 可调整大小的 NativeArray
。NativeHashMap
- 键/值对。NativeMultiHashMap
- 每个键有多个值。NativeQueue
- 先进先出 (FIFO) 队列。安全系统内置于所有 NativeContainer
类型中。此系统会跟踪在 NativeContainer
中读写的内容。
Note: All safety checks on NativeContainer
types (such as out of bounds checks, deallocation checks, and race condition checks) are only available in the Unity Editor and Play mode.
Part of this safety system is the DisposeSentinel and AtomicSafetyHandle. The DisposeSentinel
detects memory leaks and gives you an error if you haven’t freed your memory correctly. Triggering the memory leak error happens long after the leak occurred.
使用 AtomicSafetyHandle
可以在代码中转移 NativeContainer
的所有权。例如,如果两个调度的作业正在写入相同的 NativeArray
,则安全系统会抛出一个异常,并显示一条明确的错误消息,说明问题的原因和解决方法。调度违规的作业时,安全系统会抛出此异常。
在这种情况下,可以调度具有依赖关系的作业。第一个作业可以写入 NativeContainer
,一旦该作业完成执行,下一个作业就可以安全地读取和写入相同的 NativeContainer
。从主线程访问数据时,读写限制也适用。安全系统允许多个作业并行读取相同的数据。
By default, when a job has access to a NativeContainer
, it has both read and write access. This configuration can slow performance. The C# Job System doesn’t allow you to schedule a job that has write access to a NativeContainer
at the same time as another job that’s writing to it.
If a job doesn’t need to write to a NativeContainer
, mark the NativeContainer
with the [ReadOnly]
attribute, like so:
[ReadOnly]
public NativeArray<int> input;
在上面的示例中,允许多个作业同时对 NativeArray
进行只读访问。
注意:无法防止从作业中访问静态数据。访问静态数据时会绕过所有安全系统,并可能导致 Unity 崩溃。如需了解更多信息,请参阅 C# 作业系统提示和故障排除。
When creating a NativeContainer
, you must specify the memory allocation type that you need. The allocation type depends on the length of time the job runs. This way you can tailor the allocation to get the best performance possible in each situation.
There are three Allocator types for NativeContainer
memory allocation and release. You must specify the appropriate one when instantiating a NativeContainer
.
Temp
to pass NativeContainer
allocations to jobs.Temp
but is faster than Persistent
. Use it for thread-safe allocations within a lifespan of four frames. Important: You must Dispose
of this type of allocation within four frames, or the console prints a warning, generated from the native code. Most small jobs use this NativeContainer
allocation type.NativeContainer
allocation type. Don’t use Persistent
where performance is essential.例如:
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
Note: The number 1 in the example above indicates the size of the NativeArray
. In this case, it has only one array element because it only stores one piece of data in result
.
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.