コールバック
イントロ
Quantumの衝突とトリガーのコールバックは、システム信号 を介して処理されます。 特定のエンティティに対してコールバックを実行するには、2つの手順が必要です。
- エンティティへの特定のタイプのコールバックを有効にする。
- 対応する信号を実装する。
コールバックを有効にする方法とコードの記述方法を学ぶ前に、まず、さまざまなコールバックタイプと、それらが実行される原因を理解することが重要です。
コールバックのタイプ
衝突とトリガーは、物理エンジンの衝突検出ステップによって生成された2つのエンティティまたはエンティティと静的なペアのいずれかとして開始されます。 エンティティにアタッチされている物理コンポーネントの組み合わせ、およびトリガープロパティの値(true / false)に応じて、以下の表は、実行されるコールバックのタイプを示します。
エンティティ vs エンティティ
構成要素に応じて、物理演算可能なエンティティは以下のいずれかに分類されます:
- 非トリガーコライダー: 非トリガー物理コライダーと、オプションでキネマティック物理ボディを持つエンティティ。
- トリガーコライダー: トリガー物理コライダーと、オプションでキネマティック物理ボディを持つエンティティ。
- 動的ボディ: 非トリガー物理コライダーと動的(非キネマティック)物理ボディを持つエンティティ。
衝突ペアが2つのエンティティAとBで構成されている場合、これらは実行される可能性のあるコールバックです(各エンティティが属するグループによります)。
エンティティ A X B | 非トリガーコライダー | トリガーコライダー | 動的ボディ |
---|---|---|---|
非トリガーコライダー | なし | OnTrigger | OnCollision |
トリガーコライダー | OnTrigger | なし | OnTrigger |
動的ボディ | OnCollision | OnTrigger | OnCollision |
エンティティ vs 静的コライダー
一方、静的コライダーはIsTrigger
プロパティに応じて、TriggerまたはNon-Triggerのどちらかになり得ます。
以下は、衝突ペアがエンティティと静的コライダーから構成される場合に可能な組み合わせです:
コンポーネント (エンティティと静的) | 非トリガー静的コライダー | トリガー静的コライダー |
---|---|---|
非トリガーコライダー | なし | OnTrigger |
トリガーコライダー | OnTrigger | なし |
動的ボディ | OnCollision | OnTrigger |
エンティティのコールバックを有効にする
個々のエンティティに対して有効にするコールバックタイプ(および他の種類のコライダーに対して)を制御できます。これは、Unityの Entity Prototype を介して、または物理エンジンAPIの SetCallbacks 関数を介してコードで実行され、エンティティと衝突コールバックフラグを受け取ります。
エンティティプロトタイプ経由
物理コールバックは、PhysicsCollider(2D / 3D)を使用して エンティティプロトタイプ に設定できます。
各エンティティは複数のコールバックを持つことができます。
N.B.: Entity Prototype でコールバックを有効にすると、その特定のエンティティの コールバックが設定 されるだけです。引き続き、対応する 信号 をコードに実装する必要があります。詳細については、以下の コールバック信号 のセクションを参照してください。
コード経由
コールバックフラグはビットマスクであり、次に例示するようにビットごとの演算を使用して複数のコールバックタイプを指定できます。
次のスニペットは、別の動的エンティティ(OnDynamicTrigger、OnDynamicTrigger OnDynamicTriggerEnter、OnDynamicTriggerExit)に対するOnTriggerコールバックの完全なセットを有効にします。
C#
CallbackFlags flags = CallbackFlags.OnDynamicTrigger;
flags |= CallbackFlags.OnDynamicTriggerEnter;
flags |= CallbackFlags.OnDynamicTriggerExit;
// for 2D
f.Physics2D.SetCallbacks(entity, flags);
// for 3D
f.Physics3D.SetCallbacks(entity, flags);
これらは基本的なコールバックフラグです(対応する信号は、物理エンジンによって衝突が検出されなくなるまで、ティックごとに呼び出されます)。
- CallbackFlags.OnDynamicCollision
- CallbackFlags.OnDynamicTrigger
- CallbackFlags.OnStaticTrigger
そして、これらは対応するEnter / Exitコールバックです(上記とは別に有効にすることができます):
CallbackFlags.OnDynamicCollisionEnter
CallbackFlags.OnDynamicCollisionExit
CallbackFlags.OnDynamicTriggerEnter
CallbackFlags.OnDynamicTriggerExit
CallbackFlags.OnStaticCollisionEnter
CallbackFlags.OnStaticCollisionExit
CallbackFlags.OnStaticTriggerEnter
CallbackFlags.OnStaticTriggerExit
エンティティごとにコールバックを有効にする必要があるのは、デフォルトのシミュレーションをできるだけ高速にするための意図的な設計です。また、Enter / Exitコールバックは(基本的なコールバックと比較して)より多くのメモリとCPU使用率で発生するため、可能な限り無駄のないシミュレーションでは、可能な限りこれらを回避する必要があります。
コールバック信号
N.B.: エンティティ vs エンティティ および エンティティ vs 静的 の衝突とトリガーのコールバックは、統合されたシグナルAPIにグループ化されます。
2D物理演算信号は以下です:
C#
namespace Quantum {
public interface ISignalOnCollision2D : ISignal {
void OnCollision2D(Frame f, CollisionInfo2D info);
}
public interface ISignalOnCollisionEnter2D : ISignal {
void OnCollisionEnter2D(Frame f, CollisionInfo2D info);
}
public interface ISignalOnCollisionExit2D : ISignal {
void OnCollisionExit2D(Frame f, ExitInfo2D info);
}
public interface ISignalOnTrigger2D : ISignal {
void OnTrigger2D(Frame f, TriggerInfo2D info);
}
public interface ISignalOnTriggerEnter2D : ISignal {
void OnTriggerEnter2D(Frame f, TriggerInfo2D info);
}
public interface ISignalOnTriggerExit2D : ISignal {
void OnTriggerExit2D(Frame f, ExitInfo2D info);
}
}
3D物理信号は以下です:
C#
namespace Quantum {
public interface ISignalOnCollision3D : ISignal {
void OnCollision3D(Frame f, CollisionInfo3D info);
}
public interface ISignalOnCollisionEnter3D : ISignal {
void OnCollisionEnter3D(Frame f, CollisionInfo3D info);
}
public interface ISignalOnCollisionExit3D : ISignal {
void OnCollisionExit3D(Frame f, ExitInfo3D info);
}
public interface ISignalOnTrigger3D : ISignal {
void OnTrigger3D(Frame f, TriggerInfo3D info);
}
public interface ISignalOnTriggerEnter3D : ISignal {
void OnTriggerEnter3D(Frame f, TriggerInfo3D info);
}
public interface ISignalOnTriggerExit3D : ISignal {
void OnTriggerExit3D(Frame f, ExitInfo3D info);
}
}
コールバックを受信するには、対応する信号インターフェイスを少なくとも1つの有効なシステムに実装する必要があります(無効化されたシステムでは信号が実行されません)。
C#
public class PickUpSystem : SystemSignalsOnly, ISignalOnTriggerEnter3D
{
public void OnTriggerEnter3D(Frame f, TriggerInfo3D info)
{
if (!f.Has<PickUpSlot>(info.Entity)) return;
if (!f.Has<PlayerID>(info.Other)) return;
var item = f.Get<PickUpSlot>(info.Entity).Item;
var itemAsset = f.FindAsset<ItemBase>(item.Id);
itemAsset.OnPickUp(f, info.Other, itemAsset);
f.Destroy(info.Entity);
}
}
上記のコードは、信号を実装するときに使用できるさらに別の最適化の例です。SystemSignalsOnly から継承することで、システムは空の更新関数をスケジュールせずに(不必要なタスクシステムのオーバーヘッドがかかる)、信号を処理できます。
その他とFAQ
衝突コールバックを操作するときに役立つ情報:
- トリガーと静的コライダーの衝突は、法線/ポイント/貫通データを計算しません。
- UnityのStatic Colliderでは、「Asset」フィールドにQuantum DBアセットを追加できます。予想されるカスタムアセットタイプへのキャストは、静的衝突コールバックに任意のデータを追加する良い方法です。