静的コライダー
はじめに
シーンに静的コライダーを追加するには、次の3つの簡単なステップを行います。
- Unityのゲームオブジェクトに、
Quantum Static Collider
スクリプトをアタッチする。 - シーンの静的な障害物のジオメトリに合わせて、プロパティを編集する。
MapData
スクリプトを使用して、シーンをベイクする。


Unityコライダーを元に作成する
Quantumの静的コライダーは、Unityコライダーのプロパティを反映することもできます。反映したいコライダーを、Quantum Static Collider
コンポーネントのSource Collider
フィールドにドラッグ&ドロップしてください。

シェイプ
2D物理シェイプは次の通りです。
- Circle
- Box
- Polygon
注意: すべてのシェイプはHeight
フィールドを持ち、2.5Dシェイプを作成することが可能です。
3D物理シェイプは次の通りです。
- Sphere
- Box
- Mesh
設定
静的コライダーには、PhysicsMaterial
とUser Asset
を設定できます。後者は、コリジョンコールバックを通してシミュレーションで利用可能です。
Smooth Sphere Mesh Collider
Static Mesh Collider 3D
には、Smooth Sphere Mesh Collision
というオプションがあります。このオプションを有効にすると、物理ソルバーはメッシュを通常の平坦で滑らかな平面として、球とメッシュの衝突を解決します。これによって、トライアングルの角に衝突した球に回転が加わることを防ぎます。

Smooth Sphere Mesh Collision
オプションが有効なStatic Mesh Collider 3D
のメッシュが完全に平坦ではない場合、望ましくない衝突反応が生じる可能性があります。実行時の有効化/無効化
ここでは、実行時にシミュレーションの静的コライダーを有効/無効にする方法をいくつか紹介します。
物理エンジン
物理エンジンでは、静的コライダーのオン/オフを実行時に直接切り替えることができます。
静的コライダーを切り替えられるようにするには、編集時(Unity)にMode
を設定して、Map
アセットにベイクする必要があります。モードは次のように設定できます。
Immutable
(デフォルト):コライダーは実行時に有効/無効にできません。Toggleable Start On
:コライダーは実行時に切り替え可能で、初期値は有効です。Toggleable Start Off
:コライダーは実行時に切り替え可能で、初期値は無効です。

静的コライダーが切り替え可能でベイクされると、実行時にシミュレーション(Quantum)でコライダーを有効/無効にできるようになります。3Dの静的コライダーではFrame.Physics3D
、2Dの静的コライダーではFrame.Physics2D
のSetStaticColliderEnabled()
を使用します。
パラメーターとして渡すindex
は、frame.Map.StaticCollider
配列のコライダーのインデックスです。コリジョンコールバックは、TriggerInfo
/CollisionInfo
で静的コライダーのインデックス(ColliderIndex
)を返します。
重要: 無効な静的コライダーは物理クエリから無視され、衝突シグナルをトリガーしません。
手動トラッキング
静的コライダーは、物理エンジンレベルで有効/無効にできますが、これを手動で行うには様々な方法があります。
グローバルなビットセットで状態を管理
コリジョンコールバックでどの静的コライダーを考慮/無視するかを追跡するだけが目的であれば、frame.Map.StaticColliders
配列以上の長さを持つグローバルBitSet
を定義するのが、最も便利な方法です。これは、Frame
オブジェクトの一部か、シングルトンコンポーネントとして実装できます。
C#
singleton component StaticColliderState {
bitset[256] colliders;
}
これによって、コライダーのインデックスをビットセットのビットとして設定できるようになります。
C#
// ビットセットのすべてのビットを"On"に初期化して、すべてのコライダーをアクティブにする
public override void OnInit(Frame f)
{
var collidersState = f.Unsafe.GetPointerSingleton<StaticColliderState>();
for (int i = 0; i < collidersState->colliders.Length; i++) {
collidersState->colliders.Set(i);
}
}
public void OnTrigger3D(Frame frame, TriggerInfo3D info)
{
if (info.IsStatic == false) return;
// UserAssetフィールドの独自アセットを使用して、切り替え可能なコライダーを識別する
var colliderAsset = frame.FindAsset<MyColliderAsset>(info.StaticData.Asset);
if (colliderAsset == null) return;
var collidersState = frame.Unsafe.GetPointerSingleton<StaticColliderState>();
collidersState->colliders.Clear(info.StaticData.ColliderIndex);
}
値はIsSet()
から読み取り可能で、衝突シグナルを処理/無視するかを判断するために使用できます。これは、インタラクション可能な静的オブジェクトや関門のような環境、移動にIKCCCallbacks3D
を実装する際に特に便利です。
挙動による切り替え
静的コライダーはアセットであるため、実行時にはステートレスかつ不変です。しかし、静的オブジェクトを動的な条件に基づいて有効/無効にしたい場合もあります。
例えば、ステージ上のアイテムは静的な位置とトリガーコライダーで通常は表現されます。これらを静的コライダーにすることで、動的エンティティ関連のオーバーヘッドを回避できます。ただし、アイテム取得後に再出現させるクールダウンタイマーには状態が必要になります。この問題は、前のセクションで説明した概念を拡張することで解決できます。
まず、パワーアップアイテムを表す静的コライダーの状態をどこかに保持する必要があります。
C#
singleton component PowerUps {
[ExcludeFromPrototype] bitset[256] IsPowerUp;
[ExcludeFromPrototype] bitset[256] State;
[ExcludeFromPrototype] array<FP>[256] Timers;
FP SpawnCooldown;
}
次に、パワーアップアイテムの有効/無効を処理するシステムを作成します。
C#
public unsafe class MyPowerUpSystem : SystemMainThread {
public override void OnInit(Frame f)
{
var powerUps = f.Unsafe.GetPointerSingleton<PowerUps>();
for (int i = 0; i < powerUps->IsPowerUp.Length; i++)
{
var powerUp = f.FindAsset<MyPowerUpAsset>(f.Map.StaticColliders3D[i].StaticData.Asset);
if (powerUp == null) {
powerUps->IsPowerUp.Clear(i);
continue;
}
powerUps->IsPowerUp.Set(i);
powerUps->State.Set(i);
powerUps->Timers[i] = FP._0;
}
}
public override void Update(Frame f){
var powerUps = f.Unsafe.GetPointerSingleton<PowerUps>();
for (int i = 0; i < powerUps->IsPowerUp.Length; i++)
{
if (powerUps->IsPowerUp.IsSet(i) == false) continue;
if (powerUps->State.IsSet(i)) continue;
powerUps->Timers[i] -= f.DeltaTime;
if(powerUps->Timers[i] > 0) continue;
powerUps->State.Set(i);
// パワーアップアイテムの出現/再出現をレンダリングするためのコード
// VFX・SFX・ゲームオブジェクトの有効化をトリガーするためにフレームイベントを使用できる
}
}
public void OnTrigger3D(Frame frame, TriggerInfo3D info)
{
if(info.IsStatic == false) return;
var powerUps = f.Unsafe.GetPointerSingleton<PowerUps>();
if(powerUps->IsPowerUp.IsSet(info.StaticData.ColliderIndex) == false) return;
if(powerUps->State.IsSet(info.StaticData.ColliderIndex) == false) return;
powerUps->State.Clear(info.StaticData.ColliderIndex);
powerUps->Timers[info.StaticData.ColliderIndex] = powerUps->SpawnCooldown;
// 無効状態を視覚的に伝える(例:Unityのゲームオブジェクトを無効にするフレームイベントをトリガーする)
}
Back to top