静的コライダー
はじめに
シーンに静的コライダーを追加するには、3つの簡単な手順を実行します。
- Unity GameObjectにQuantum Static Colliderスクリプトをアタッチします。
- プロパティを編集して、シーン内の静的障害物に必要なジオメトリに類似させます。
- MapDataスクリプトを介してシーンをベイクします。
ソースとしてのUnituコライダー
Quantumの静的コライダーは、Unityコライダーからプロパティをミラーリングすることもできます。
ミラーリングは、Quantum Static ColliderコンポーネントのSource Collider
フィールドに該当するコライダーをドラッグアンドドロップするだけでおこなえます:
形状
2D物理形状は次のとおりです。
- Circle
- Box
- Polygon
N.B.: どれも、2.5D形状の作成を可能にするHeight
フィールドがあります。
3D物理形状は次のとおりです。
- Sphere
- Box
- Mesh
設定
静的コライダーには、PhysicsMaterialとUser Asset を取り付けることができます。後者は、衝突コールバックを介してシミュレーションで使用できます。
滑らかな平面メッシュコライダー
静的メッシュコライダー 3D
には、滑らかな平面メッシュ衝突
というオプションがあります。このオプションをオンにすると、物理ソルバーは球体とメッシュの衝突を、あたかもメッシュが通常の平らで滑らかな平面であるかのように解決します。これにより、三角形のエッジと衝突した球体にスピンを加えることができなくなります。
ランタイム時の有効化・無効化
このセクションでは、シミュレーションのランタイムで静的コライダーを有効化・無効化するいくつかのアプローチをご紹介します。
物理エンジン
物理エンジンでは、ランタイムに性的コライダのオン/オフを直接切り替えることができます。
スタティックコライダをトグル可能にするには、そのMode
を edit-time (Unity) で設定し、 Map
アセットにベイクする必要があります。モードは以下のように設定できます。
Immutable
(ドフォルト): コライダーをランタイムで有効または無効にすることはできません。Toggleable Start On
: コライダーはランタイムでトグルでき、__enabled__を開始します。Toggleable Start Off
: コライダーはランタイムに切り替えられ、__disabled__を開始します。
静的コライダがトグル可能とマークされ、ベイクされると、シミュレーション(Quantum)からランタイムに、3Dと2Dの静的コライダに対して、それぞれFrame.Physics3D
とFrame.Physics2D
のSetStaticColliderEnabled()
を使って、コライダを有効にしたり無効にしたりすることができるようになります。
パラメータとして渡される index
は、frame.Map.StaticColliders
配列内のコライダーのインデックスです。コリジョンコールバックは、静的コライダーのインデックス(ColliderIndex
)を、その TriggerInfo
や CollisionInfo
の StaticData
の一部として返します。
重要: 無効になった静的メッシュコライダは、物理クエリによって無視され、コリジョンシグナルは発生しません。
手動トラッキング
静的コライダは物理エンジンレベルで有効/無効にすることができますが、同じことを手動で行うには様々なアプローチがあります。
状態のためにグローバルなビットセットを維持する
コリジョンコールバックでどのスタティックコライダーを無視するか、あるいは考慮するかを追跡することだけが目的であれば、最も便利な方法は、frame.Map.StaticColliders
配列と同じ長さかそれ以上のグローバルなBitSet
を定義することです。これは、Frame
オブジェクトの一部として、またはシングルトンコンポーネントとして行うことができます。
C#
singleton component StaticColliderState {
bitset[256] colliders;
}
これにより、colliderのインデックスを持つbitsetインスタンスを使用して、そのビットを設定することができます。
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
を実装する場合に特に有効です。
Toggle with Behaviour
静的なコライダーはアセットです。つまり、ステートレスでランタイム時にイミュータブルです。ただし、動的な条件に基づいて、静的なオブジェクトが有効化・無効化されるべきインスタンスが存在します。
例えば、pick-upsは通常静的な位置を表しコライダーをトリガーしますが、これらを静的なコライダーにすると動的なエンティティに菅レづけすぎることを開始します。残念ながら、pick-upクールダウンの後にpower-upをリスポーンするタイマーはステートを要求します。この難問は、前の章で述べたコンセプトで解消することができます。
まず、power-upを表す静的コライダーのステートをどこかに置く必要があります。
C#
singleton component PowerUps {
[ExcludeFromPrototype] bitset[256] IsPowerUp;
[ExcludeFromPrototype] bitset[256] State;
[ExcludeFromPrototype] array<FP>[256] Timers;
FP SpawnCooldown;
}
power-upの有効化・無効化を処理するシステムが作成されます。
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