静的コライダー
はじめに
シーンに静的コライダーを追加するには、次の三つの簡単なステップを行います。
- UnityのGameObjectに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を設定することができます。後者は、衝突コールバックを通じてシミュレーション内で利用可能です。
スムーススフィアメッシュコライダー
Static Mesh Collider 3D
には、Smooth Sphere Mesh Collision
というオプションがあります。このオプションをオンにすると、物理ソルバーはメッシュとスフィアの衝突を、メッシュが通常の平坦で滑らかな面であるかのように解決します。これにより、三角形のエッジに衝突した際にスフィアに回転が加わるのを防ぎます。

実行時の有効化 / 無効化
このセクションでは、シミュレーション内での実行時に静的コライダーを有効化および無効化するためのいくつかのアプローチを紹介します。
物理エンジン
静的コライダーは、物理エンジン内で実行時に直接オン・オフを切り替えることが可能です。
静的コライダーが切り替え可能であるためには、そのMode
を編集時に(Unityで)設定し、Map
アセットにベイクする必要があります。モードは次のように設定できます:
Immutable
(デフォルト):コライダーは実行時に有効または無効にすることができません。Toggleable Start On
:コライダーは実行時に切り替えることができ、初期状態は__有効__です。Toggleable Start Off
:コライダーは実行時に切り替えることができ、初期状態は__無効__です。

静的コライダーが切り替え可能としてマークされ、ベイクされると、シミュレーション(Quantum)内で実行時にコライダーを有効または無効にすることが可能になります。これには、3D静的コライダーにはFrame.Physics3D
を、2D静的コライダーにはFrame.Physics2D
のSetStaticColliderEnabled()
を使用します。
渡す必要があるindex
は、frame.Map.StaticColliders
配列内のコライダーのインデックスです。衝突コールバックは、TriggerInfo
またはCollisionInfo
の一部として、静的コライダーのインデックス(ColliderIndex
)を返します。
重要: 無効にされた静的メッシュコライダーは物理クエリで無視され、衝突シグナルを引き起こしません。
マニュアルトラッキング
静的コライダーは物理エンジンレベルで有効/無効にすることができますが、この切り替えを手動で行うには、さまざまなアプローチがあります。
グローバルビットセットで状態を管理
衝突コールバックで無視するべき静的コライダーを追跡するだけが目的であれば、最も便利なアプローチは、frame.Map.StaticColliders
配列と同じ長さまたはそれ以上の長さを持つグローバルBitSet
を定義することです。これは、Frame
オブジェクトの一部として、またはシングルトンコンポーネントとして実装できます。
C#
singleton component StaticColliderState {
bitset[256] colliders;
}
これにより、コライダーのインデックスを使用してビットセットインスタンスでビットを設定できるようになります。
C#
// loops through the bitset to initialize all bits as "On" to mark all colliders as active
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;
// Use a custom asset slotted in the UserAsset field to identify toggleable colliders
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);
// Other code visualizing the spawned / re-enabled power-up
// can use frame event to trigger VFX, SFX, re-enable visual / GameObject
}
}
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;
// Remember to communicate the disabled state visually, e.g. trigger a frame event to disable the GameObject in Unity
}
Back to top