衝突は、2つの3Dオブジェクトが3D空間内で接触する際に発生します。カスタマイズされた衝突処理のために、BasePartには一連の衝突イベントと衝突フィルタリング技術があり、どの物理アセンブリが他と衝突するかを制御できます。
衝突イベント
衝突イベントは、2つのBasePartsが3D空間で接触したり、接触を停止したりする際に発生します。これらの衝突は、TouchedおよびTouchEndedイベントを通じて検出できます。これらのイベントは、いずれかのパートのCanCollideプロパティの値に関係なく発生します。パーツの衝突処理を考慮する際には、以下の点に注意してください。
- パーツのCanCollideプロパティは、他のパーツと物理的に衝突するかどうかに影響します。たとえCanCollideが無効になっていても、TouchedおよびTouchEndedイベントを通じて接触と非接触を検出できます。
- TouchedおよびTouchEndedイベントは、物理的な動きの結果としてのみ発火し、パーツのPositionやCFrameの変更によって他のパーツと交差したり、交差を停止したりする場合には発火しません。
Touched
Touchedイベントは、BasePartが他のパーツまたはTerrainボクセルと接触したときに発火します。このイベントは物理シミュレーションの結果としてのみ発火し、パーツのPositionやCFrameが明示的に設定されて他のパーツやボクセルと交差する場合には発火しません。
以下のコードパターンは、TouchedイベントをカスタムonTouched()関数に接続する方法を示しています。このイベントは、衝突に関与する他のパーツを示すotherPart引数を関数に送信します。
local part = workspace.Part
local function onTouched(otherPart)
print(part.Name .. " が " .. otherPart.Name .. " と衝突しました")
end
part.Touched:Connect(onTouched)Touchedイベントは、動いているオブジェクトが「落ち着く」位置に「定着」する際や、マルチパーツモデルが関与する衝突の際に、微妙な物理的衝突に基づいて短時間に複数回発火する可能性があります。必要以上にTouchedイベントをトリガーしないように、インスタンス属性を通じて「クールダウン」期間を強制するシンプルなデバウンスシステムを実装できます。
local part = workspace.Part
local COOLDOWN_TIME = 1
local function onTouched(otherPart)
if not part:GetAttribute("Touched") then
print(part.Name .. " が " .. otherPart.Name .. " と衝突しました")
part:SetAttribute("Touched", true) -- 属性をtrueに設定
task.wait(COOLDOWN_TIME) -- クールダウン期間を待つ
part:SetAttribute("Touched", false) -- 属性をリセット
end
end
part.Touched:Connect(onTouched)TouchEnded
TouchEndedイベントは、BasePartの全衝突境界が他のBasePartまたは満たされたTerrainボクセルの境界を出たときに発火します。このイベントは物理シミュレーションの結果としてのみ発火し、パーツのPositionやCFrameが明示的に設定されて他のパーツやボクセルとの交差を停止する場合には発火しません。
以下のコードパターンは、TouchEndedイベントをカスタムonTouchEnded()関数に接続する方法を示しています。Touchedと同様に、このイベントは他のパーツを示すotherPart引数を関数に送信します。
local part = workspace.Part
local function onTouchEnded(otherPart)
print(part.Name .. " は " .. otherPart.Name .. " との接触を終了しました")
end
part.TouchEnded:Connect(onTouchEnded)衝突の概要
Touchedは衝突が発生したことを知らせますが、どこで発生したのか、どの方向から来たのか、どれほど強かったのかはわかりません。物理エンジンからの詳細な接触データを取得するには、パーツに対してBindToCollisionSummaries()を呼び出します。これはコールバックを受け取り、データが不要になったときに切断できるRBXScriptConnectionを返します。これはTouchedとは別のAPIであるため、Touchedハンドラ内から呼び出さないでください。
コールバックは、物理ステップが完了した後、フレームごとに1回実行されます。これは、そのフレーム中にパーツが関与したすべての衝突の概要を含むテーブルを受け取ります。各概要は、サブスクライブされたパーツと他のパーツとの間の1つの接触パッチを説明します。概要は固定されており、変更できません。各概要には以下のフィールドがあります:
| フィールド | 型 | 説明 |
|---|---|---|
| Time | number | サブステップのシミュレーション時間。 |
| Part0 | BasePart | サブスクライブされたパーツ。 |
| Part1 | BasePart | ペアの他のパーツ。 |
| Point | Vector3 | 世界空間での平均接触点。 |
| Normal | Vector3 | 単位法線。常にPart0から離れる方向を指します。 |
| RelativeVelocity | Vector3 | 接触点でのPart1のPart0に対する速度。衝突が解決される前に測定されます。 |
| Area | number | 接触パッチの推定面積。 |
正面からの衝撃速度を取得するには、RelativeVelocityとNormalのドット積を取ります。斜めのヒットやスライディングを検出するには、RelativeVelocityの接線成分を使用します。力に近い値を得たい場合は、速度とパーツのAssemblyMassを組み合わせます。
local part = workspace.Part
local function onCollision(summaries)
for _, summary in summaries do
local impactSpeed = summary.RelativeVelocity:Dot(summary.Normal)
if impactSpeed > 10 then
print("衝撃が発生しました", summary.Point, "速度", impactSpeed)
end
end
end
local connection = part:BindToCollisionSummaries(onCollision)
-- 後で、概要が不要になったとき
connection:Disconnect()衝突の概要を使用する際には、以下の点に注意してください:
- 概要は、物理シミュレーションを実行するネットワークオーナーでのみ生成されます。これはクライアントまたはサーバーである可能性があります。概要は複製されません。他のクライアントが衝突について知る必要がある場合は、概要を処理し、必要なデータのみを独自のリモートイベントを通じて送信してください。
- CanCollideがfalseに設定されているパーツは、衝突の概要を生成しません。
- 複雑な非凸パーツは、同じペアのパーツに対して複数の概要を生成する可能性があります。
- 2つのスリーピングパーツ間の接触は記録されません。
- 処理コストは、サブスクライブされたパーツの数に比例して増加し、場所内の衝突の総数には依存しません。
衝突フィルタリング
衝突フィルタリングは、どの物理パーツが他のパーツと衝突するかを定義します。多数のオブジェクトのフィルタリングを衝突グループを通じて構成することができます。または、NoCollisionConstraintインスタンスを使用してパーツ間の衝突を制御することもできます。
衝突グループ
衝突グループを使用すると、BasePartsを専用のグループに割り当て、他のグループのオブジェクトと衝突するかどうかを指定できます。衝突しないグループ内のパーツは、互いに完全に通過します。たとえ両方のパーツがCanCollideプロパティをtrueに設定していてもです。衝突グループは、WorkspaceまたはWorldModelの単位で作成および構成されます。
スタジオの衝突グループエディタを通じて、衝突グループを簡単に設定できます。これはスタジオのウィンドウ ⟩ 3Dメニューからアクセスできます。
グループの登録
Workspaceは、独自の構成可能な衝突グループの状態を保存します。さらに、任意のWorldModelは、クエリのために独自の衝突グループを使用することを選択できます。
エディタには、名前を変更したり削除したりできない1つのデフォルト衝突グループが含まれています。すべてのBasePartsは、他のグループに割り当てられない限り、このデフォルトグループに自動的に属し、デフォルトグループ内の他のすべてのオブジェクトと衝突します。
新しい衝突グループを作成するには:
デフォルトでは、グループはWorkspaceに登録されますが、場所に少なくとも1つのWorldModelがある場合、衝突グループエディタの上部に選択ドロップダウンが表示されます。このドロップダウンを使用して、異なるWorldModelインスタンス間で衝突グループを構成します。

任意のWorldModelに対して、ワークスペースの衝突グループを使用をオンに切り替えることで、そのクエリにWorkspaceの衝突グループを使用させることができます。

エディタパネルの上部にあるグループを追加ボタンをクリックし、新しいグループ名を入力してEnterを押します。新しいグループは、リストビューの両方の列、またはテーブルビューの左列と上部の行の両方に表示されます。

必要に応じてこのプロセスを繰り返し、各グループにユニークで説明的な名前を選択します。開発中にグループの名前を変更するには、そのフィールドをクリックするか、選択して名前を変更ボタンをクリックします。

グループの衝突を構成する
デフォルトの構成では、すべてのグループ内のオブジェクトは互いに衝突します。1つのグループ内のオブジェクトが別のグループ内のオブジェクトと衝突しないようにするには、該当する行/列のボックスのチェックを外します。
以下の例では、Cubesグループ内のオブジェクトはDoorsグループ内のオブジェクトと衝突しません。

オブジェクトをグループに割り当てる
登録したグループにオブジェクトを割り当てるには、スタジオエディタを通じて:
衝突グループの一部として適格な1つ以上のBasePartsを選択します。
行の**⊕**ボタンをクリックしてグループに割り当てます。オブジェクトは一度に1つの衝突グループにしか属せず、新しいグループに配置すると現在のグループから削除されます。

割り当てられると、新しいグループはオブジェクトのCollisionGroupプロパティに反映されます。

StudioSelectableグループ
スタジオのツールは、3Dビューポートでクリックしたときに選択候補となるオブジェクトを決定するために衝突フィルタリングシステムを使用します。割り当てられた衝突グループがStudioSelectableと衝突しないオブジェクトは無視されます。
たとえば、レースゲームのチェックポイントが大きな透明なパーツで定義されている場合、これらをCheckpoints衝突グループに割り当て、そのグループをStudioSelectableと衝突しないように設定することで、基盤となるマップジオメトリを編集する際に邪魔にならないようにできます。

プラグインコードでは、カーソルの下にあるパーツを見つける際に、RaycastParamsの衝突グループフィルタとして"StudioSelectable"を割り当てることをお勧めします。これにより、プラグインがスタジオツールから期待される選択メカニクスに一致します。
local UserInputService = game:GetService("UserInputService")
local raycastParams = RaycastParams.new()
raycastParams.CollisionGroup = "StudioSelectable" -- 規約に従うため
raycastParams.BruteForceAllSlow = true -- CanQueryが"false"のパーツも選択できるようにする
local mouseLocation = UserInputService:GetMouseLocation()
local mouseRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
local filteredSelectionHit = workspace:Raycast(mouseRay.Origin, mouseRay.Direction * 10000, raycastParams)パーツ間フィルタリング
2つの特定のパーツ間の衝突を防ぐために、衝突グループを設定せずに、たとえば車両のホイールとシャーシの間で、No Collision制約を検討してください。利点には以下が含まれます:
- 衝突グループや構成スクリプトは必要ないため、カスタマイズされた衝突フィルタリングを持つモデルを簡単に作成して共有できます。
- 接続されたパーツは互いに衝突しませんが、他のオブジェクトとは衝突できます。
キャラクターの衝突を無効にする
Robloxのプレイヤーキャラクターはデフォルトで互いに衝突します。これにより、キャラクターが特定のエリアに到達するために互いの上にジャンプするなど、興味深いが意図しないゲームプレイが発生する可能性があります。この動作が望ましくない場合、次のScriptをServerScriptServiceに配置することで防ぐことができます。
local Players = game:GetService("Players")
workspace:RegisterCollisionGroup("Characters")
workspace:CollisionGroupSetCollidable("Characters", "Characters", false)
local function onDescendantAdded(descendant)
-- すべてのパーツの子孫に対して衝突グループを設定
if descendant:IsA("BasePart") then
descendant.CollisionGroup = "Characters"
end
end
local function onCharacterAdded(character)
-- 物理設定のために既存および新しい子孫を処理
for _, descendant in character:GetDescendants() do
onDescendantAdded(descendant)
end
character.DescendantAdded:Connect(onDescendantAdded)
end
Players.PlayerAdded:Connect(function(player)
-- プレイヤーのキャラクターが追加されたときに検出
player.CharacterAdded:Connect(onCharacterAdded)
end)モデルの衝突
Modelオブジェクトはパーツのコンテナであり、BasePartから継承していないため、BasePart.TouchedやBasePart.TouchEndedイベントに直接接続することはできません。モデルが衝突イベントをトリガーするかどうかを判断するには、その子をループして、各子BasePartにカスタムonTouched()およびonTouchEnded()関数を接続する必要があります。
以下のコードサンプルは、マルチパーツモデルのすべてのBasePartsを衝突イベントに接続し、他のパーツとの衝突の総数を追跡します。
local model = script.Parent
local numTouchingParts = 0
local function onTouched(otherPart)
-- モデルが自分自身と交差しているインスタンスを無視
if otherPart:IsDescendantOf(model) then return end
-- モデルパーツが接触している数を増加
numTouchingParts += 1
print(model.Name, "が", otherPart.Name, "と交差しました | モデルパーツの接触数:", numTouchingParts)
end
local function onTouchEnded(otherPart)
-- モデルが自分自身と交差を解除しているインスタンスを無視
if otherPart:IsDescendantOf(model) then return end
-- モデルパーツが接触している数を減少
numTouchingParts -= 1
print(model.Name, "が", otherPart.Name, "から交差を解除しました | モデルパーツの接触数:", numTouchingParts)
end
for _, child in model:GetChildren() do
if child:IsA("BasePart") then
child.Touched:Connect(onTouched)
child.TouchEnded:Connect(onTouchEnded)
end
endメッシュおよびソリッドモデルの衝突
MeshPartおよびPartOperation(ソリッドモデリングによって結合されたパーツ)はBasePartのサブクラスであるため、メッシュおよびソリッドモデルのパーツは通常のパーツと同じ衝突イベントおよび衝突フィルタリングオプションを継承します。ただし、メッシュやソリッドモデルのパーツは通常、より複雑なジオメトリを持つため、衝突処理のために物理的境界が視覚的表現とどれだけ正確に一致するかを決定する特有のCollisionFidelityプロパティがあります。
CollisionFidelityプロパティには、忠実度とパフォーマンスへの影響が最も低いものから高いものまで、以下のオプションがあります:
- ボックス — 小さなまたは非対話型のオブジェクトに最適なバウンディング衝突ボックスを作成します。
- ハル — 突出した凹みや空洞の少ないオブジェクトに適した凸ハルを生成します。
- デフォルト — 凹面をサポートする近似衝突形状を生成し、複雑なオブジェクトに適しています。
- 精密凸分解 — 最も正確な忠実度を提供しますが、視覚の1:1表現ではありません。このオプションは最も高価なパフォーマンスコストがかかり、エンジンが計算するのに時間がかかります。

衝突忠実度オプションのパフォーマンスへの影響とそれを軽減する方法についての詳細は、パフォーマンス最適化を参照してください。