Photon Quantum3 円状範囲内のEntityを高速で取得するブロードフェーズクエリ

特徴

  • 通常のクエリより高速
  • 並列処理されるため大量にクエリを使用する時にパフォーマンスが向上する
  • 物理システム実行後に結果を取得できる

実装手順

  1. クエリ結果を取得するQTNファイルを作成する
  2. クエリを登録するSystemを作成する
  3. 作成したSystemをSystemConfigにQuantum.Core.PhysicsSystem2Dより前に登録する
  4. クエリの結果を受け取るSystemを作成する

コード

// 1.クエリ結果を取得するQTNファイルを作成する
BroadphaseQueriesLink.qtn

component BroadphaseQueriesLink
{
    PhysicsQueryRef AttackZoneQueryRef;
}
// 2.クエリを登録するSystemを作成する

using Quantum;

public unsafe class ProjectileHitQueryInjectionSystem : SystemMainThread
{
    public override void Update(Frame frame)
    {
        // Filterのコンポーネントを持っているEntityを全て取得
        var projectileFile = frame.Unsafe.FilterStruct<Filter>();
        // 繰り返しに使う変数
        var projectile = default(projectileFile);

        // 取得したEntityを繰り返す
        while (projectileFilter.Next(&projectile))
            {
                // クエリを登録
                projectile.Component->AttackZoneQueryRef = frame.Physics3D.AddOverlapShapeQuery(
                    projectile.Transform->Position,
                    projectile.Transform->Rotation,
                    Shape3D.CreateSphere(5),
                    1);
            }
    }
    
    public unsafe struct Filter
    {
        public EntityRef EntityRef;
        public Transfomr3D* Transform;
        public BroadphaseQueriesLink* Component;
    }
}
// 4.クエリの結果を受け取るSystemを作成する

using Quantum;

public unsafe class ProjectileHitRetrievalSystem : SystemMainThread
{
    public override void Update(Frame frame)
    {
        // Filterのコンポーネントを全て持っているEntityを取得
        var projectileFilter = frame.Unsafe.FilterStruct<Filter>();
        var projectile = default(ProjectileFilter);

        while (projectileFilter.Next(&projectile))
        {
            // ヒットしたEntityの結果を取得
            if (frame.Physics3D.TryGetQueryHits(projectile.Component->AttackZoneQueryRef, out var attackZoneHit))
            {
                for (int i = 0; i < attackZoneHit.Count; i++)
                {
                    // 処理
                }
            }
        }
    }
        public unsafe struct Filter
    {
        public EntityRef EntityRef;
        public Transfomr3D* Transform;
        public BroadphaseQueriesLink* Component;
    }
}

解説

QTN

PhysicsQueryRef型には実行するクエリを保持するために必要で、クエリを実行する全てのEntityにこのComponentをアタッチする必要がある。

クエリ登録System

  • このSystemは必ずSystemConfigのQuantum.Core.PhysicsSystem2Dより前に登録しないと何も受け取ることができない。
  • FilterStruct<>()によってFilter内のComponentがアタッチされているEntityを取得する。
  • .Physics3D.AddRaycastQueryの引数
    • クエリを実行する場所:FPVector3
    • クエリを実行する角度:FPQuaternion
    • 取得するLayer:int

結果を受け取るSystem

  • 物理演算後に値が取得されるので、物理演算後に登録しましょう
  • Physics3D.TryGetQueryHitsはPhysicsQueryRefの中にあるデータが無い場合はfalseを返す

コメント

タイトルとURLをコピーしました