mcpField
P
player-physics

player-physics

github.com/decentraland開発4288 回インストール今日更新
リポジトリ

player-physics について

Decentraland のシーン開発者向けプレイヤー物理ガイドです。Physics API でローカルプレイヤーに瞬間的または継続的な力を加える方法に加え、トリガー領域とモバイルでの注意点を説明します。

主な機能

  1. 01インパルスとノックバックの適用
  2. 02指定時間の力の適用
  3. 03距離に応じた反発力の作成
  4. 04エンティティが所有する力の解除
  5. 05ローカル方向からワールド方向への変換
  6. 06プレイヤートリガーの衝突レイヤーの説明

活用シーン

  1. 01発射台や爆発ノックバックの作成
  2. 02風の通路、コンベヤー、重力場の実装
  3. 03点を中心とした反発領域の作成
  4. 04プレイヤー物理トリガー領域のデバッグ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/decentraland/sdk-skills --skill player-physics

インストール後、Claude Code で/player-physicsを入力して読み込まれたか確認します。

同梱ファイルreferences/physics-patterns.md

詳細

Decentraland のプレイヤー物理演算

@dcl/sdk/ecs の Physics API を使用して、プレイヤーのアバターに力を加えます。物理演算はすべてローカルプレイヤーにのみ影響します。

このスキルが必要な理由 — Transform の誤用

プレイヤーの Transform(engine.PlayerEntity 上)はエンジンによって制御されており、シーンコードからは読み取り専用です。Transform.getMutable、Transform.createOrReplace、または .position/.rotation の直接変更によって書き込んでも、何も起こりません。コードはコンパイルされ、システムも実行されますが、エラーは発生せず、アバターも動きません。

プレイヤーを浮かせる、空中に留める、押す、ノックバックさせる、または継続的な力を加える場合は、このスキルの Physics API を使用してください。 特定の位置への即時テレポートや滑らかな移動には、~system/RestrictedActions の movePlayerTo を使用してください(スキル:player-avatar)。

// WRONG — has no effect in-world
const t = Transform.getMutable(engine.PlayerEntity)
t.position.y += 0.1  // ignored every frame

// CORRECT — lift the player upward
import { Physics } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'
Physics.applyImpulseToPlayer(Vector3.create(0, 50, 0))   // one-shot upward launch
// or, sustained lift / hover:
const lifter = engine.addEntity()
Physics.applyForceToPlayer(lifter, Vector3.create(0, 1, 0), 12)  // continuous upward force
// stop with: Physics.removeForceFromPlayer(lifter)

インパルス(一度だけの押し出し)

Physics.applyImpulseToPlayer(direction, magnitude?) を使用して、瞬間的な力を一度だけ加えます。大きさを別途指定すると、方向は自動的に正規化されます。同じフレーム内で複数回呼び出すと、力は累積されます。発射台、ジャンプ、爆発などに使用します。

ノックバック(点から遠ざける)

Physics.applyKnockbackToPlayer(sourcePos, magnitude, radius?, falloff?) を使用して、プレイヤーを発生源の位置から遠ざけます。発生源からプレイヤーへの方向は自動的に計算されます。

KnockbackFalloff のオプション
フォールオフ動作
KnockbackFalloff.CONSTANT半径内では距離にかかわらず同じ大きさ(デフォルト)
KnockbackFalloff.LINEAR半径の端で 0 になるまで滑らかに直線的に減少
KnockbackFalloff.INVERSE_SQUARE物理的に現実的な急激な減衰

プレイヤーが発生源とまったく同じ位置にいる場合、真上に押し出されます。負の大きさを指定すると、プレイヤーはその点に引き寄せられます。applyRepulsionForceToPlayer() でも同じフォールオフ値を使用できます。ほとんどの範囲効果では、自然で予測しやすい KnockbackFalloff.LINEAR をおすすめします。

継続的な力

エンティティ(力の「所有者」)で識別される持続的な方向の力を加えます。異なるエンティティによる複数の力は重なり合います。

  • 適用:Physics.applyForceToPlayer(entity, direction, magnitude?)
  • 削除:Physics.removeForceFromPlayer(entity)

トリガーゾーンと組み合わせて、風のトンネル、コンベアベルト、重力場などに使用します。

時間指定の力

固定時間だけ力を加えるには、Physics.applyForceToPlayerForDuration(entity, seconds, direction, magnitude?) を使用します。時間が経過すると自動的に終了します。

反発力

距離に応じてフォールオフする、固定点から遠ざける継続的な力を加えます。この力は毎フレーム再計算されます。Physics.applyRepulsionForceToPlayer(entity, position, magnitude, radius) を使用します。位置は明示的に渡す必要があります。エンティティの Transform から自動的に取得されるわけではありません。Physics.removeForceFromPlayer(entity) で削除します。

座標変換(ローカル方向からワールド方向へ)

Transform.localToWorldDirection(entity, localDir) を使用して、ローカル方向をワールド空間に変換します。エンティティの向きに対して力を加える場合(例:「この大砲の前方へ」)に使用します。

クイックリファレンス

メソッド種類説明
Physics.applyImpulseToPlayer(dir, mag?)一度だけ指定方向への瞬間的な押し出し
Physics.applyKnockbackToPlayer(pos, mag, radius?, falloff?)一度だけ点から遠ざける
Physics.applyForceToPlayer(entity, dir, mag?)継続有効な間、継続的に押し出す
Physics.removeForceFromPlayer(entity)制御継続的な力を止める
Physics.applyForceToPlayerForDuration(entity, secs, dir, mag?)時間指定時間経過で自動的に終了する力
Physics.applyRepulsionForceToPlayer(entity, pos, mag, radius)継続点から距離に応じて押し出す
Transform.localToWorldDirection(entity, dir)ユーティリティローカル方向をワールド空間に変換

トリガーゾーンのコライダーレイヤー — どのプレイヤーがトリガーを発火させるか

Physics.* は常にローカルプレイヤーに作用します。TriggerArea から力を加える場合、コライダーマスクによって、どのアバターがコールバックを発火させるかが決まります(テストシーン 5,5-collider-layers で検証済み)。

マスク発火する対象
ColliderLayer.CL_MAIN_PLAYERローカルプレイヤーのみ
ColliderLayer.CL_PLAYERリモートアバターのみ(ローカルプレイヤーは対象外)
CL_PLAYER | CL_MAIN_PLAYERローカルとリモートの両方
ColliderLayer.CL_PHYSICSどのアバターに対しても発火しません(キャラクターではなく、シーンのメッシュや壁が対象です)

プレイヤーの物理演算に使うトリガーゾーンには、CL_MAIN_PLAYER を使用してください。 コールバックはローカルプレイヤーに対してのみ発火するため、リモートかローカルかを判定する必要がなく、力は作用可能な唯一のアバターに加わります。CL_PLAYER のみを使ったジャンプ台は、ローカルプレイヤーに対して発火しないため(リモートアバターに対してのみ発火します)、その上に立っているプレイヤーをジャンプさせません。これはよくあるバグです。

CL_PLAYER | CL_MAIN_PLAYER を使う場合は、result.trigger?.entity === engine.PlayerEntity で判定してください。result.trigger?.entity は、トリガーに入ったエンティティです。注:result.triggeredEntity はトリガーエリア自体のエンティティであり、進入したエンティティではありません。そのため、これを PlayerEntity と比較しても、誰が入ったかは判別できません。

滑空中の力

プレイヤーが滑空している(グライダーを開いている)間は、力の挙動が異なります。

  • 継続的な力(applyForceToPlayer、applyForceToPlayerForDuration、applyRepulsionForceToPlayer)は1.5 倍強くなります。開いたグライダーが気流を受けるため、風のゾーンや気流に対する反応がより敏感になります。
  • 継続的な力の上向き成分によって、滑空中のプレイヤーを上昇させることができます。AvatarLocomotionSettings の glidingFallingSpeed が制限するのは下降速度のみで、上向きの動きを打ち消しません。そのため、斜めや垂直方向の気流は、力の向きに沿ってプレイヤーを押し上げます。これにより、上昇気流や風の通り道を作れます。
  • 一度だけ加えるインパルス(applyImpulseToPlayer、applyKnockbackToPlayer)は、滑空の影響を受けません。グライダーを開いていても閉じていても、挙動は同じです。

モバイルの動作はデスクトップとまったく同じではありません

モバイルアプリの v1.15.0(2026年10月)では、Unity と同等の動作を目指す最初の調整として、カプセルサイズ、段差の高さ、ジャンプの軌道と重力、走行速度、空中制御が反映され、下向きのプレイヤー用レイキャストも修正されました。これにより、傾斜したジオメトリ上で正しい hitDistance が報告されるようになりました。ただし、これは最初の調整であり、完全な同等性には至っていません。以下の項目は引き続き未対応で、対応時期も未定です(ドキュメントのコミット 5f212e3)。

  • 傾斜、端、壁、着地、動くプラットフォームの挙動は、引き続き Unity と異なります。滑空の挙動も同様です(修正をレビュー中)。
  • **シーンのコライダーの厚さが 1 cm 未満の場合、上からのみ衝突します。**厚さ 0.5 cm の壁、薄い不可視の床板、紙のように薄い傾斜路は、モバイルでは横から通り抜けてしまいます。すべてのコライダーに最低 1 cm の厚みを持たせてください。手間のかからない予防策であり、ここで最もすぐ実践できるルールです。
  • **不可視の障害物や一部の SDK の衝突レイヤーは、モバイルではプレイヤーをまったくブロックしません。**プレイエリアの区切り、キル境界、「範囲内に留まる」ルールを、不可視のコライダーだけで実現しないでください。TriggerArea と movePlayerTo を組み合わせるか、プレイヤーから見えるジオメトリで補ってください。
  • スポーン、着地、ジャンプのアニメーションと移動のブレンドがありません。そのため、アバターの動きが硬く見えます。モバイルクライアントでは再生されないアニメーションのタイミングに、仕掛けを合わせないでください。

デスクトップで「ぎりぎり」動作するよう調整した段差、縁石、棚の高さは、スマートフォンでは登れないことも、逆に登れるべきでないのに登れてしまうこともあります。また、インパルスやノックバック後の着地位置も異なる場合があります。通行できるジオメトリには余裕を持たせ、強制移動を伴う仕掛けには着地しやすいエリアを設けてください。精密なプラットフォームアクションを公開する前に、実機で確認してください。また、TweenSequence はモバイルではアニメーションを実行しません(animations-tweens)。そのため、これを使った動くプラットフォームは、スマートフォンでは動きません。モバイルでの同等性に関する一覧は advanced-input → モバイルに関する考慮事項 をご覧ください。

コード例の全体(ジャンプ台、風のトンネル、反発フィールド、座標変換)については、{baseDir}/references/physics-patterns.md をご覧ください。

コメント