Unity6 非同期オブジェクト生成: 技術資料

概要

このドキュメントでは、Unity における非同期オブジェクト生成の実装について説明します。このシステムは、大量のオブジェクト(例: 100,000 個)をメインスレッドをブロックせずに生成し、滑らかな実行パフォーマンスを確保することを目的としています。

コンポーネント

1. スクリプト

a) SimpleSpawn

このスクリプトは、オブジェクトの非同期生成を管理し、生成完了後のロジックを処理します。

using UnityEngine;

public class SimpleSpawn : MonoBehaviour
{
    [SerializeField] private ToSpawn objectToSpawn;
    [SerializeField] private ToSpawn[] _spawnedObjects;

    private async void Start()
    {
        _spawnedObjects = await InstantiateAsync(objectToSpawn, 100000);
        // 非同期処理完了後の処理
        OnInstantiationComplete();
    }

    // 生成完了後に行う処理
    private void OnInstantiationComplete()
    {
        Debug.Log("全ての生成が完了: オブジェクト数 " + _spawnedObjects.Length);
        foreach (var obj in _spawnedObjects)
        {
            // 例: 各オブジェクトに対して何かする
        }
    }
}

b) AsyncTest

このスクリプトは、非同期処理中もメインスレッドが影響を受けないことを示すために、Update() 関数をログ出力します。

using UnityEngine;

public class AsyncTest : MonoBehaviour
{
    void Update()
    {
        Debug.Log("Update");
    }
}

c) ToSpawn

生成対象のオブジェクトを表します。

using UnityEngine;

public class ToSpawn : MonoBehaviour
{
}

2. シーン設定

ゲームオブジェクト

  • GameObject: SimpleSpawn スクリプトをアタッチします
  • GameObject (1): AsyncTest スクリプトをアタッチします

プレハブ

  • Cube プレハブ: 生成対象のオブジェクト。
  • ToSpawn スクリプトをアタッチします

詳細

1. 非同期でのオブジェクト生成

SimpleSpawnStart() メソッドは、非同期関数 (InstantiateAsync) を呼び出して、Cube プレハブを 100,000 個生成します。このプロセスはメインスレッドをブロックしないため、AsyncTestUpdate() メソッドはスムーズに実行され続けます。

2. 完了処理

生成プロセスが完了すると、OnInstantiationComplete() メソッドが呼び出され、生成されたオブジェクトの総数をログに記録し、さらに処理を行います。

3. コンソールログ

Update()OnInstantiationComplete() 内の Debug.Log() ステートメントにより、以下を確認できます。

  • 非同期プロセスがメインスレッドに影響を与えないこと。
  • 生成プロセスが完了した状態。

結果

コンソール出力

  1. Update ログ:
    AsyncTest スクリプトは、非同期操作中に継続的に Update メッセージをログ出力します。
  2. 生成完了ログ:
    すべてのオブジェクトが生成された後、SimpleSpawn スクリプトは以下のメッセージをログ出力します。
   全ての生成が完了: オブジェクト数 100000

インスペクター表示

  • SimpleSpawn スクリプトの Spawned Objects 配列に、すべての生成されたオブジェクトが表示されます。
  • プレハブは事前に定義されたプロパティ(例: Mesh RendererBox Collider)を保持します。

ベストプラクティス

  1. 非同期メソッドの活用
    非同期生成は、大規模なオブジェクト生成中のUIやゲームのカクつきを防ぎ、スムーズなゲームプレイを保証します。
  2. 重要なイベントのログ出力
    Debug.Log() を使用してプロセスを監視し、潜在的なボトルネックを特定します。
  3. オブジェクトプロパティの最適化
    プレハブが軽量で最適化されていることを確認し、メモリと処理の負荷を最小限に抑えます。

仕様の更新

  • 分割生成: インスタンス化を小さなバッチに分割して、メモリ使用量をさらに最適化します。
  • 進行状況のフィードバック: 生成中の進行状況を示す視覚的またはテキストによるフィードバックを追加します。
  • エラーハンドリング: 生成前にプレハブが有効であることを確認するチェックを実装します。

1. スクリプトの更新

SimpleSpawnの更新

このスクリプトは、オブジェクトの非同期生成を管理し、生成完了後のロジックを処理します。

進行状況のフィードバック

非同期生成中に進行状況を Debug.Log() を使ってリアルタイムで記録し、生成状況を確認できます。

using UnityEngine;
using System.Collections.Generic;
using System.Threading.Tasks;

public class SimpleSpawn : MonoBehaviour
{
    [SerializeField] private GameObject objectToSpawn;
    [SerializeField] private List<GameObject> _spawnedObjects = new List<GameObject>();
    [SerializeField] private int batchSize = 1000;
    [SerializeField] private int totalObjects = 100000;

    private async void Start()
    {
        await InstantiateInBatchesAsync();
        OnInstantiationComplete();
    }

    // Unity6のObject.InstantiateAsyncを使用した分割生成
    private async Task InstantiateInBatchesAsync()
    {
        int created = 0;

        while (created < totalObjects)
        {
            int count = Mathf.Min(batchSize, totalObjects - created);

            // 同時にオブジェクトを生成する
            var handle = InstantiateAsync(objectToSpawn, count);

            while (!handle.isDone)
            {
                await Task.Yield(); // 完了を待機
            }

            if (handle.Result != null)
            {
                _spawnedObjects.AddRange(handle.Result); // 配列をリストに追加
            }
            else
            {
                Debug.LogError("Failed to instantiate batch.");
            }

            created += count;
            Debug.Log($"Progress: {created}/{totalObjects}");
            await Task.Yield(); // メインスレッドの負荷を軽減
        }
    }

    // 生成完了後に行う処理
    private void OnInstantiationComplete()
    {
        Debug.Log("全ての生成が完了: オブジェクト数 " + _spawnedObjects.Count);
    }
}

結果

コンソール出力

進行状況ログ: 生成中に進行状況がリアルタイムで記録されます。

このメッセージの間にUpdateメッセージが表示されているのを確認します

Progress: 1000/100000 Progress: 2000/100000 ...

生成完了ログ: すべてのオブジェクトが生成された後、SimpleSpawn スクリプトは以下のメッセージをログ出力します。

全ての生成が完了: オブジェクト数 100000

C#,Unity

Posted by hidepon