UnsafeUtility.Mallocとは
Unmanaged memoryを確保することができる。
// 確保するサイズ var size = UnsafeUtility.SizeOf<int>(); // メモリアライメント var alignment = UnsafeUtility.AlignOf<int>(); // アンマネージドメモリの確保 void* ptr = UnsafeUtility.Malloc(size, alignment, Allocator.Persistent);
UnsafeUtility.Freeとは
確保したUnmanaged memoryを解放する。
// 確保したメモリの解放
UnsafeUtility.Free(ptr, Allocator.Persistent);
使用例
// 弾の共通データ public struct SharedBulletParam { public float Speed; public float Damage; } // 個別に持つ弾データ(NativeArrayとして持つのでBlittable型である必要) public unsafe struct Bullet { public SharedBulletParam* SharedBulletParamPtr; public float Angle; // 角度 public float Lifespan; // 生存時間 } void Initialize() { // 確保するメモリサイズ var size = UnsafeUtility.SizeOf<SharedBulletParam>(); // メモリアライメント var alignment = UnsafeUtility.AlignOf<SharedBulletParam>(); // アンマネージドメモリの確保 var sharedBulletPtr = (SharedBulletParam*)UnsafeUtility.Malloc( size, alignment, Allocator.Persistent); const int BulletCount = 1000; var bullets = new NativeArray<Bullet>(BulletCount, Allocator.Persistent); for (int i = 0; i < BulletCount; i++) { bullets[i] = new Bullet { // 各インスタンスに共通データのポインタを持たせる SharedBulletParamPtr = sharedBulletPtr, }; } // ※使い終わったらNativeArrayとMallocしたポインタを解放すること }
使用例2-1
struct SampleStr { public int Param1; public float Param2; public SampleStr(int index) { Param1 = index; Param2 = index + index / 10f; } public override string ToString() { return $"{Param1}, {Param2}"; } } void Start() { // 確保するメモリサイズ var size = UnsafeUtility.SizeOf<SampleStr>(); // メモリアライメント var alignment = UnsafeUtility.AlignOf<SampleStr>(); // アンマネージドメモリの確保 var ptr = (SampleStr*)UnsafeUtility.Malloc(size, alignment, Allocator.Persistent); // ---------------------------------------- // 構造体の値をポインタにコピー SampleStr sample = new SampleStr(8); UnsafeUtility.CopyStructureToPtr(ref sample, ptr); // > 8, 8.88 Debug.Log(*ptr); // ---------------------------------------- // ポインタが指す値を構造体にコピー var dest = new SampleStr(); UnsafeUtility.CopyPtrToStructure(ptr, out dest); // > 8, 8.88 Debug.Log(dest); UnsafeUtility.Free(ptr, Allocator.Persistent); }
使用例2-2
大変分かりやすい
struct SampleStr { public int Param1; public float Param2; public SampleStr(int index) { Param1 = index; Param2 = index + index / 10f; } public override string ToString() { return $"{Param1}, {Param2}"; } } void Start() { // SampleStrを8個生成 var nativeArray = new NativeArray<SampleStr>(8, Allocator.Persistent); for (var i = 0; i < nativeArray.Length; i++) { nativeArray[i] = new SampleStr(i); } // 拡張メソッドとして実装されているのでこれで取得可能 var ptr = (SampleStr*) nativeArray.GetUnsafePtr(); // > "0, 0" // ※"Debug.Log(nativeArray[0])"と同等 Debug.Log(*(ptr)); // > "2, 2.2" // ※"Debug.Log(nativeArray[2])"と同等 Debug.Log(*(ptr + 2)); // > "3.3" // ※アロー演算子(->)でフィールドにアクセスできる // ※"Debug.Log(nativeArray[3].Param2)"と同等 Debug.Log((ptr + 3)->Param2); nativeArray.Dispose(); }