# NativeContainer 構造体のコピー

> Copy and reference multiple native containers.

[ネイティブコンテナ](/engine/6000.0/manual/scripting/optimization/job-system/native-container.md) は値型です。変数に割り当てられると、Unityは `NativeContainer` 構造体をコピーします。この構造体にはネイティブコンテナのデータを格納する場所へのポインター ([`AtomicSafetyHandle`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle.md) など) が含まれます。`NativeContainer` のコンテンツ全体をコピーするわけではありません。

これは、同じメモリ領域を参照する `NativeContainer` 構造体のコピーが複数存在し、そのすべてに同じ主要レコードを参照する `AtomicSafetyHandle` オブジェクトが存在する可能性があるということです。


**NativeContainer オブジェクトのコピーの仕組み:**
![](/api/media?file=/engine/6000.0/media/images/native-container-diagram.png)

上図に示す `NativeArray` 構造体の 3 つの異なるコピーは、同じ実際のコンテナを表しています。各コピーは保存された同じデータ、および元の `NativeArray` と同じ安全データを指しています。ただし、`NativeArray` の各コピーは、ジョブがそのコピーで実行できる内容を示す互いに異なるフラグを持っています。安全データへのポインターは、フラグとの組み合わせで、`AtomicSafetyHandle` を構成します。

## バージョン番号

`NativeContainer` を破棄する場合、`NativeContainer` 構造体のすべてのコピーは、元の `NativeContainer` が無効になることを認識する必要があります。元の `NativeContainer` を廃棄すると、`NativeContainer` のデータを保持していたメモリブロックの割り当てが解除されます。この場合、`NativeContainer` の各コピーに格納されているデータへのポインターは無効になり、使用するとアクセス違反になる可能性があります。

`AtomicSafetyHandle` も同様に `NativeContainer` インスタンスで無効になる主要レコードを指しています。ただし、安全システムは主要レコードのメモリ割り当てを解除しないため、アクセス違反のリスクを回避できます。

代わりに、各レコードにはバージョン番号が追加されます。バージョン番号のコピーは、そのレコードを参照する各 `AtomicSafetyHandle` 内に格納されます。NativeContainer が破棄されると、Unity は `Release()` を呼び出し、主要レコードのバージョン番号を更新します。こうすることで、このレコードは他の `NativeContainer` インスタンスに再利用できるようになります。

残りの各 `AtomicSafetyHandle `は、保存されているバージョン番号と主要レコードのバージョン番号を比較して、`NativeContainer` が破棄されたかどうかをテストします。Unity は、[`CheckReadAndThrow`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/check-read-and-throw.md) や [`CheckWriteAndThrow`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/check-write-and-throw.md) などのメソッドの呼び出しの一部として、このテストを自動的に実行します。

## 動的ネイティブコンテナの静的ビュー

動的ネイティブコンテナは、可変サイズのコンテナです。[`NativeList<T>`](https://docs.unity3d.com/Packages/com.unity.collections@latest/index.html?subfolder=/api/Unity.Collections.NativeList-1.html) (Collections パッケージで使用可能) などの要素を継続的に追加できます。これは、[`NativeArray<T>`](/engine/6000.0/script-reference/unity-collections/native-array-1.md) などの静的ネイティブコンテナがサイズを変更できないのとは対照的です。

動的ネイティブコンテナを使用する場合、ビューと呼ばれる別のインターフェースからデータに直接アクセスすることもできます。ビューを使用すると、`NativeContainer` オブジェクトのデータをコピーしたり所有権を取得したりすることなく、エイリアスを作成できます。ビューの例として、ネイティブコンテナの要素ごとにデータにアクセスできる Enumerator (列挙子) オブジェクトがあります。また、`NativeList` を `NativeArray` のように扱うために使用できる [`NativeList<T>.AsArray`](https://docs.unity3d.com/Packages/com.unity.collections@latest/index.html?subfolder=/api/Unity.Collections.NativeList-1.html#Unity_Collections_NativeList_1_AsArray) などのメソッドもあります。

動的ネイティブコンテナのサイズを変更する場合、ビューは通常スレッドセーフではありません。これは、ネイティブコンテナのサイズを変更すると、Unity がメモリ内のデータの格納場所を変更し、ビューの格納するポインターが無効になるためです。

### 補助バージョン番号

動的ネイティブコンテナのサイズの変更に対応するため、安全システムには `AtomicSafetyHandle` に補助バージョン番号が記録されています。バージョン更新の仕組みと似ていますが、ここでは主要レコードに格納された 2 つ目のバージョン番号を使用し、1 つ目のバージョン番号とは別に更新します。

補助バージョン番号を使用するには、[`UseSecondaryVersion`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/use-secondary-version.md) を使用して、ビューを `NativeContainer` に保存されているデータに設定します。ネイティブコンテナのサイズを変更する操作や、既存のビューを無効にする操作には、`CheckWriteAndThrow` ではなく [`CheckWriteAndBumpSecondaryVersion`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/check-write-and-bump-secondary-version.md) を使用します。また、ネイティブコンテナへ書き込むジョブがスケジュールされるたびにビューが自動的に無効になるよう、`NativeContainer` に [`SetBumpSecondaryVersionOnScheduleWrite`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/set-bump-secondary-version-on-schedule-write.md) を設定する必要があります。

ビューを作成して `AtomicSafetyHandle` をコピーする場合は、[`CheckGetSecondaryDataPointerAndThrow`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/check-get-secondary-data-pointer-and-throw.md) を使用して、ネイティブコンテナのメモリーへのポインターをビューにコピーしても安全であることを確認します。

## 特殊フォルダー

一時的なネイティブコンテナで作業するときに使える特別なハンドルが 2 つあります。

* [`GetTempMemoryHandle`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/get-temp-memory-handle.md): `Allocator.Temp` で割り当てられたネイティブコンテナで使用できる `AtomicSafetyHandle` を返します。現在の一時メモリ範囲が終了すると、Unity はこのハンドルを自動的に無効にするため、自分で解除する必要はありません。特定の `AtomicSafetyHandle` が `GetTempMemoryHandle` によって返されるハンドルかどうかをテストするには、 `IsTempMemoryHandle` を使用します。
* [`GetTempUnsafePtrSliceHandle`](/engine/6000.0/script-reference/unity-collections-low-level-unsafe/atomic-safety-handle/get-temp-unsafe-ptr-slice-handle.md): 安全でないメモリで保持された一時的なネイティブコンテナに使用できるグローバルハンドルを返します。例えば、スタックメモリから構築された `NativeSlice` などです。このハンドルを使用するコンテナをジョブに渡すことはできません。

## 追加リソース

* [カスタム NativeContainer の実装](/engine/6000.0/manual/scripting/optimization/job-system/native-container/custom-nativecontainer.md)
* [カスタム NativeContainer の例](/engine/6000.0/manual/scripting/optimization/job-system/native-container/custom-nativecontainer-example.md)
