パスファインディング は、キャラクターを論理的なパスに移動させるプロセスで、障害物や (オプションで) 危険な材料や定義された領域を避けます。
ナビゲーションビジュアライズ
パスファインディングレイアウトとデバッグを助けるために、Studio はナビゲーションメッシュと 変更者 レーベルをレンダリングできます。有効にするには、 ナビゲーションメッシュ と 変更者 レーベルを 2>ビジュアル化オプション2> ウィジェ
ナビゲーションメッシュを有効にすると、色付きのエリアは、キャラクターが歩水泳か、Swim する場所を表示し、色付きのエリアは、ジャンプして、AgentCanJump をAgentCanJump に設定した場合、パスを作成すると、小さな矢印が、キャラクターがジャンプし、 True</
パスファインドモジュール を有効にすると、テキストラベルは パスファインドモジュール を使用する際に考慮される特定の材料と領域を指し示します。
既知の限定
パスファインド機能は、効率的な処理と最高パフォーマンスを保証するための制限を特定します。
縦型配置の制限
パスファインド計算は、特定の垂直境界内のパーツだけを考慮します:
- 境界下限 — 下位の Y 座標が -65,536 より小さいパーツは無視されます。
- アッパーバウンドリー — 上限 Y コーディネートのパーツは、65,536スタッドを超えているため無視されます。
- 垂直スパン — 最下部の底からの垂直距離 Y コーディネートから最上部のトップ Y コーディネートまでの垂直距離; 65,536スタッドを超えると、パス検索システムは、パス検索コンピューターのパス検索コンピューターでパス検索コンピューターを無視します。
検索距離制限
パスファインドから開始して最終点までの直接視界距離は 3,000 スタッドを超えてはなりません。この距離を超えると、NoPath ステータスが結果となりま状況。
パスを作成中
パス検索は、PathfindingService とその CreatePath() 機能を通じて始動されます。
ローカルスクリプト
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath()
CreatePath() は、キャラクター (エージェント) がパスをどのように移動するかを調整するオプションのパラメーターのテーブルを受け入れます。
キー | 説明 | タイプ | デフォルト |
---|---|---|---|
AgentRadius | エージェント範囲、in studs。障害からの最小限の分離を決定するのに便利。 | 整数 | 2 |
AgentHeight | エージェントの高さ、in studs。空きスペースがこの値より小さい、例えば階段の下のスペースのように、非乗り越え可能であることが示されます。 | 整数 | 5 |
AgentCanJump | パスファインド中にジャンプすることが許可されていますか。 | ブールーン | true |
AgentCanClimb | パスファインド中に TrussParts をクライムすることが許可されています。 | ブールーン | false |
WaypointSpacing | パス内のインターミディエートポイント間のスペース。如果math.huge を設定すると、中間のウェイポイントはありません。 | 番号 | 4 |
Costs | 材料の表または定義された PathfindingModifiers とそのコストで移動。 ユーザーエージェントが特定の材料/領域を他の領域より好むようにするのに便利。 「modifiers」で詳細を参照してください。 | テーブル | nil |
ローカルスクリプト
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentRadius = 3,AgentHeight = 6,AgentCanJump = false,Costs = {Water = 20}})
エージェントがパスファインド中に TrussParts をクライムすることがあります。これは、パスを作成するときに AgentCanClimb を true に設定した場
ローカルスクリプト - トラスの登りパス
local PathfindingService = game:GetService("PathfindingService")local path = PathfindingService:CreatePath({AgentCanClimb = true,Costs = {Climb = 2 -- 登り坂のコスト; デフォルトは 1}})
パスに沿って移動
このセクションでは、プレイヤーのキャラクターのために次のパスファインドスクリプトを使用します。読み込み中にテストするには:
- コードを LocalScript 内の StarterCharacterScripts にコピーします。
- 11行を Vector3 に編集し、プレイヤーキャラクターが到達できるデスティネーション。
- 次のセクションを通じて、パス計算とキャラクターの移動について学びましょう。
ローカルスクリプト - キャラクターパスファインド
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- パスを計算
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- パスウェイポイントを取得する
waypoints = path:GetWaypoints()
-- パスがブロックされるかどうかを検出
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- 障害物がパスをさらに下にあるかどうかチェック
if blockedWaypointIndex >= nextWaypointIndex then
-- パスが再計算されるまで、パスブロックを検出しないでください
blockedConnection:Disconnect()
-- 新しいパスを再計算するための関数を呼び出す
followPath(destination)
end
end)
-- 次の移動ポイントへの移動が完了したときに検出
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- ウェイポイントインデックスを増加し、次のウェイポイントに移動する
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- 最開始に 2番目のウェイポイントに移動します (最初のウェイポイントはパススタートです)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
followPath(TEST_DESTINATION)
パスを計算する
有効なパスを作成した後、CreatePath() を含む、必要なパスを計算する必要があります。 Datatype.Vector3 の両方の開始点と目的地の両方で、Path:ComputeAsync() を呼び出してください。
ローカルスクリプト - キャラクターパスファインド
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- パスを計算
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
end
ウェイポイントを取得する
Class.Patパス が計算されると、 通路 が開始から終了までを追跡するシリーズの Path:GetWaypoints() が含まれます。これらのポイントは、1>Class.Patパス:GetWaypoints()1> 関数で集めることができます。
ローカルスクリプト - キャラクターパスファインド
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- パスを計算
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- パスウェイポイントを取得する
waypoints = path:GetWaypoints()
end
end
パス移動
各ウェイポイントは、位置 ( Vector3 ) とアクション ( 2> Class.Humanoid:MoveTo
ローカルスクリプト - キャラクターパスファインド
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- パスを計算
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- パスウェイポイントを取得する
waypoints = path:GetWaypoints()
-- パスがブロックされるかどうかを検出
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- 障害物がパスをさらに下にあるかどうかチェック
if blockedWaypointIndex >= nextWaypointIndex then
-- パスが再計算されるまで、パスブロックを検出しないでください
blockedConnection:Disconnect()
-- 新しいパスを再計算するための関数を呼び出す
followPath(destination)
end
end)
-- 次の移動ポイントへの移動が完了したときに検出
if not reachedConnection then
reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- ウェイポイントインデックスを増加し、次のウェイポイントに移動する
nextWaypointIndex += 1
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- 最開始に 2番目のウェイポイントに移動します (最初のウェイポイントはパススタートです)
nextWaypointIndex = 2
humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
ブロックされたパスを処理する
多くの Roblox 世界はダイナミックです。部品が移動したり、床が落ちたりする可能性があります。これは、Path.Blocked イベントを接続し、キャラクターが目的地に到達するを防ぐことができます。これを処理するには、Class.Path.Blockedイベントを接続し、ブロックされたパスを再コンピュートします。
ローカルスクリプト - キャラクターパスファインド
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath()
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local TEST_DESTINATION = Vector3.new(100, 0, 100)
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- パスを計算
local success, errorMessage = pcall(function()
path:ComputeAsync(character.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- パスウェイポイントを取得する
waypoints = path:GetWaypoints()
-- パスがブロックされるかどうかを検出
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- 障害物がパスをさらに下にあるかどうかチェック
if blockedWaypointIndex >= nextWaypointIndex then
-- パスが再計算されるまで、パスブロックを検出しないでください
blockedConnection:Disconnect()
-- 新しいパスを再計算するための関数を呼び出す
followPath(destination)
end
end)
end
end
パスファインディングの修正
デフォルトでは、Path:ComputeAsync() は、スタート地点と目的地の間の最短の パス を返しますが、ジャンプを避けようとします。これは、いくつかの状況で不自然に見えます - たとえば、水の上をジャンプするよりも、パスを水の上をジオメトリ的に短くするために移動することがありま
さらにパス検索を最適化するために、パス検索モディファイアーを実装して、さまざまな 素材 、領域 、または 2>障害物2> の周りでより賢いパスを計算できます。
素材コストを設定
Class.Terrain と BasePart 素材を使用しているときは、Costs テーブルを含めることができます。1>Class.PathfindingService:CreatePath()|CreatePath()1> 内のす
Costs テーブルにあるキーは、Enum.Material 名前を表示するストリング名でなければなりません。たとえば、Water は、1>Enums.Material.Water1> 名前のための4>Cost4>です。
ローカルスクリプト - キャラクターパスファインド
local PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,Mud = 5,Neon = math.huge}})
領域と協力
In some cases, 材料の好み は十分ではありません。たとえば、キャラクターが 定義された領域 を避ける必要がある場合などです。これは、PathfindingModifier オブジェクトを追加することで達成できます。
危険な領域周辺の Anchored パーツを作成し、CanCollide プロパティを false に設定します。
部品に PathfindingModifier インスタンスを挿入し、Label プロパティを見つけ、 危険ゾーン のような名前を割り当てます。
Inклюide a Costs table within CreatePath() containing a matching key and associating numeric value. A modifier can be defined as non-traversable by setting its value to math.huge .
ローカルスクリプト - キャラクターパスファインドlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {DangerZone = math.huge}})
障害物を無視する
場合により、実在しないと思われる障害物をパスファインドすることが便利です。これにより、特定の物理ブロックを通過するパスを計算でき、失敗した計算を完了することなく済みます。
オブジェクトの周りに Anchored パーツを作成し、CanCollide プロパティを false に設定します。
部品に PathfindingModifier インスタンスを挿入し、PassThrough プロパティを有効にします。
さあ、ゾンビ NPC からプレイヤーキャラクターへのパスが計算されると、パスはドアを超えて拡張され、ゾンビがそれをトラベルするように促します。ゾンビがドアを開けることができない場合でも、ドアの後ろのキャラクターを「聞こう」として反応します。
パスファインドリンク
通常は通過できない空間のパスを見つける必要があります。たとえば、渓谷のように。PathfindingLink オブジェクトを通じて、次の方位点に到達するカスタムアクションを実装できます。これは、Class.PathfindingLink オブジェクトを通じて実装できます。
上の島の例を使用すると、エージェントがすべての橋を歩く代わりにボートを使用できます。
この例を使用して PathfindingLink を作成するには:
視覚化とデバッグをサポートするために、 パスファインドリンク をオプションビューポートの右上隅の ビジュアルオプション ウィジェットから切り替えます。
ボートの座席に一つ、ボートの着陸ポイントの近くに一つの Attachments を作成します。
ワークスペースに PathfindingLink オブジェクトを作成し、 アタッチメント0 と アタッチメント1 プロパティをスタートと終了のアタッチメントにそれぞれ割り当てます。
ボートの名前を含めた有意義な名前を UseBoat に、 Label プロパティに割り当てます。この名前は、パス検索スクリプトでフラグとして使用されて、エージェントが開始リンクポイントに到達すると、カスタムアクションをトリガーするようになります。
In include a Costs table within CreatePath() 含めて、Water キーとカスタムキーを含む、1> Class.PathfindingLink.Label|Label1> プロパティ名に一致するカスタムキーを含める。4> Water4> を
ローカルスクリプト - キャラクターパスファインドlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})Class.PathfindingLink.Label|Label モジュール名を変更すると、Humanoid:MoveTo() の代わりに、Class.PathfindingLink.Label|Label の名前を追加し、1>Class.Humanoid:MoveTo()1> の代わりに別のアクションを実行します。この場合、4>Class.Human
ローカルスクリプト - キャラクターパスファインドlocal PathfindingService = game:GetService("PathfindingService")local Players = game:GetService("Players")local RunService = game:GetService("RunService")local path = PathfindingService:CreatePath({Costs = {Water = 20,UseBoat = 1}})local player = Players.LocalPlayerlocal character = player.Characterlocal humanoid = character:WaitForChild("Humanoid")local TEST_DESTINATION = Vector3.new(228.9, 17.8, 292.5)local waypointslocal nextWaypointIndexlocal reachedConnectionlocal blockedConnectionlocal function followPath(destination)-- パスを計算local success, errorMessage = pcall(function()path:ComputeAsync(character.PrimaryPart.Position, destination)end)if success and path.Status == Enum.PathStatus.Success then-- パスウェイポイントを取得するwaypoints = path:GetWaypoints()-- パスがブロックされるかどうかを検出blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)-- 障害物がパスをさらに下にあるかどうかチェックif blockedWaypointIndex >= nextWaypointIndex then-- パスが再計算されるまで、パスブロックを検出しないでくださいblockedConnection:Disconnect()-- 新しいパスを再計算するための関数を呼び出すfollowPath(destination)endend)-- 次の移動ポイントへの移動が完了したときに検出if not reachedConnection thenreachedConnection = humanoid.MoveToFinished:Connect(function(reached)if reached and nextWaypointIndex < #waypoints then-- ウェイポイントインデックスを増加し、次のウェイポイントに移動するnextWaypointIndex += 1-- ボートが使用されている場合は、「ボートを使用」ラベルです。そうでない場合は、次のボートに移動しますif waypoints[nextWaypointIndex].Label == "UseBoat" thenuseBoat()elsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endelsereachedConnection:Disconnect()blockedConnection:Disconnect()endend)end-- 最開始に 2番目のウェイポイントに移動します (最初のウェイポイントはパススタートです)nextWaypointIndex = 2humanoid:MoveTo(waypoints[nextWaypointIndex].Position)elsewarn("Path not computed!", errorMessage)endendfunction useBoat()local boat = workspace.BoatModelhumanoid.Seated:Connect(function()-- エージェントが座っている場合は、ボートを開始しますif humanoid.Sit thentask.wait(1)boat.CylindricalConstraint.Velocity = 5end-- 島との関係で制限位置を検出するlocal boatPositionConnectionboatPositionConnection = RunService.PostSimulation:Connect(function()-- 島の隣にボートを停止するif boat.CylindricalConstraint.CurrentPosition >= 94 thenboatPositionConnection:Disconnect()boat.CylindricalConstraint.Velocity = 0task.wait(1)-- エージェントを降りると続行しますhumanoid.Sit = falsehumanoid:MoveTo(waypoints[nextWaypointIndex].Position)endend)end)endfollowPath(TEST_DESTINATION)
ストリーミングの対応
In-experience インスタンスストリーミング は、プレイヤーのキャラクターが世界中で動くたびに 3D コンテンツを動的に読み込み、読み込み直します。スペースストリームをそのデバイスにストリームアウトするための新しいサブセットと、既存のサブセットの一部がストリームアウトする可能性があります。
ストリーミング有効のエクスペリエンスで PathfindingService を使用するための次のベストプラクティスを考慮してください:
ストリーミングは、キャラクターがそのパスを沿って移動すると、ブロックまたはアンブロックすることができるパスをブロックまたはアンブロックできます。たとえば、キャラクターが森林を走り抜くと、木が前方の場所にストリームされ、パスを邪魔します。ストリーミングをスムーズにパスファイン
パス検索の共通のアプローチは、計算、パスの目的地を現存の 宝箱 モデルの位置に設定、など、世界中のサーバーか
この問題に対処するために、BasePart を持つ目的地を持つ persistent モデル内の PersistentLoaded の位置を設定することを検討してください。持続モデルは、プレイヤーが参加するとすぐに読み込まれ、イベントが終了すると永続モデルにアク