mcpField
U
unity-ai-navigation

unity-ai-navigation

github.com/nice-wolf-studio開発4060 回インストール6 週間前に更新
リポジトリ

unity-ai-navigation について

Unity 開発者向けに、Unity 6 の AI ナビゲーションと推論をまとめたスキルガイドです。NavMesh の構築、経路探索、動的障害物、ONNX モデルを扱います。

主な機能

  1. 01NavMesh の構築とベイク
  2. 02Agent の経路探索と移動
  3. 03動的障害物の管理
  4. 04Off-Mesh Link の設定
  5. 05Sentis による ONNX 推論

活用シーン

  1. 01実行時または編集時の NavMesh 設定
  2. 02キャラクター移動と経路状態の確認
  3. 03動的障害物やサーフェス間リンクの処理
  4. 04Unity での ONNX モデル実行

インストール

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

$npx skills add https://github.com/nice-wolf-studio/unity-claude-skills --skill unity-ai-navigation

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

同梱ファイルreferences/navmesh-guide.mdreferences/sentis-ml.md

詳細

Unity 6 AI とナビゲーションガイド

ソース:Unity 6.3 LTS ドキュメント(6000.3)

AI ナビゲーションの概要

パッケージ: com.unity.ai.navigation(Unity 6000.3 向け v2.0.11)

AI Navigation パッケージは、NavMesh ベースのナビゲーションと経路探索を可能にする高水準のコンポーネントシステムです。ランタイムおよび編集時の NavMesh 構築、動的な障害物の管理、特殊なアクション(ジャンプ、ドアなど)向けのリンクシステムに対応しています。

コアコンポーネント
コンポーネント用途
NavMeshSurface特定のエージェントタイプ向けに NavMesh を定義して構築します
NavMeshAgentキャラクターの経路探索と移動
NavMeshObstacle動的な障害物の回避
NavMeshModifierトランスフォーム階層に基づいて NavMesh の生成に影響を与えます
NavMeshModifierVolumeボリュームに基づいて NavMesh の生成に影響を与えます
NavMeshLink同一または異なる NavMesh サーフェスを接続します

NavMesh のセットアップ

NavMesh のベイク
  1. GameObject に NavMeshSurface コンポーネントを追加します
  2. Agent Type を設定します(このサーフェスを使用できるエージェントを指定します)
  3. Use Geometry を Render Meshes または Physics Colliders に設定します
  4. Collect Objects モード(All、Volume、Current Hierarchy、NavMeshModifier only)を設定します
  5. Bake をクリックするか、ランタイムに BuildNavMesh() を呼び出します
NavMeshSurface のプロパティ
プロパティ説明
Agent Typeこのサーフェスを使用できる NavMesh Agent の設定
Default AreaWalkable(デフォルト)、Not Walkable、Jump、および29種類のカスタムタイプ
Use GeometryRender Meshes または Physics Colliders(コライダーを使用すると、エッジにより近いナビゲーションが可能です)
Generate Linksベイク中に収集した GameObject 間の接続を自動作成します
Collect Objectsすべての GameObject、Volume、Current Hierarchy、NavMeshModifier only
Include Layersレイヤーに基づいて GameObject をフィルターします(デフォルト:Everything)
高度なベイクパラメーター
パラメーター説明
Override Voxel Size精度(デフォルト:エージェントの半径あたり3ボクセル)
Override Tile Sizeタイルの寸法(デフォルト:256ボクセル)。小さいほどカービングの精度が向上します
Minimum Region Areaしきい値を下回る、接続されていないメッシュセグメントを削除します
Build Height Meshキャラクター配置用の高さデータを生成します

ベイク中は、NavMeshAgent または NavMeshObstacle を持つ GameObject がシステムによって除外されます。

ランタイム NavMesh ベイク
using UnityEngine;
using Unity.AI.Navigation;

public class RuntimeNavMeshBaker : MonoBehaviour
{
    NavMeshSurface surface;

    void Start()
    {
        surface = GetComponent<NavMeshSurface>();
        surface.BuildNavMesh();
    }

    public void RebakeNavMesh()
    {
        surface.UpdateNavMesh(surface.navMeshData);
    }
}

NavMeshAgent

NavMeshAgent コンポーネントは、経路探索と移動制御の両方を処理します。

追加方法:Add Component > Navigation > NavMesh Agent

基本的な移動
using UnityEngine;
using UnityEngine.AI;

public class MoveTo : MonoBehaviour
{
    public Transform goal;

    void Start()
    {
        NavMeshAgent agent = GetComponent<NavMeshAgent>();
        agent.destination = goal.position;
    }
}
エージェントのプロパティ

ステアリング: Speed、Angular Speed、Acceleration、Stopping Distance、Auto Braking

障害物回避: Radius、Height、Quality(None から High)、Priority(0~99。数値が小さいほど優先度が高くなります)

エージェントは優先度の高いエージェントを避け、優先度の低いエージェントを無視します。

経路探索: Auto Traverse OffMesh Link、Auto Repath、Area Mask

エージェントのスクリプトパターン
using UnityEngine;
using UnityEngine.AI;

public class AIController : MonoBehaviour
{
    NavMeshAgent agent;

    void Start() { agent = GetComponent<NavMeshAgent>(); }

    public void MoveToTarget(Vector3 target) { agent.SetDestination(target); }

    bool HasReachedDestination()
    {
        if (!agent.pathPending
            && agent.remainingDistance <= agent.stoppingDistance
            && (!agent.hasPath || agent.velocity.sqrMagnitude == 0f))
            return true;
        return false;
    }

    public void StopMoving() { agent.isStopped = true; }
    public void ResumeMoving() { agent.isStopped = false; }
    public void WarpTo(Vector3 position) { agent.Warp(position); }
}
部分経路

目的地に到達できない場合、エージェントは到達可能な最寄りの場所まで部分経路を生成します。

if (agent.pathStatus == NavMeshPathStatus.PathPartial)
    Debug.Log("Destination unreachable, using partial path");
else if (agent.pathStatus == NavMeshPathStatus.PathInvalid)
    Debug.Log("No valid path found");

NavMeshObstacle

エージェントが回避する動的な障害物を定義します。追加方法:Add Component > Navigation > NavMesh Obstacle

形状: Box(Center + Size)または Capsule(Center + Radius + Height)

カービング
プロパティ説明
Move Threshold移動する障害物の更新を開始する距離
Time To Stationary停止状態と判定されるまでの秒数
Carve Only Stationary移動していないときのみカービングします
  • カービングあり: NavMesh のトポロジを動的に変更します(樽、木箱、ドアなど)
  • カービングなし: メッシュを変更せずに除外ゾーンを作成します(移動するキャラクターなど)
using UnityEngine;
using UnityEngine.AI;

public class DynamicObstacle : MonoBehaviour
{
    NavMeshObstacle obstacle;

    void Start()
    {
        obstacle = GetComponent<NavMeshObstacle>();
        obstacle.carving = true;
        obstacle.carveOnlyStationary = true;
    }

    public void SetBlocking(bool blocking) { obstacle.enabled = blocking; }
}

オフメッシュリンク(NavMeshLink)

個別の NavMesh サーフェスを接続します。ドア、ジャンプポイント、段差、はしごなどに使用します。

追加方法:GameObject > AI > NavMesh Link または Add Component > Navigation > NavMesh Link

プロパティ説明
Agent Type通行できるエージェントの種類
Start/End Transformリンクの端に配置する GameObject
Widthリンクの幅
Bidirectional双方向の通行
Area TypeWalkable、Not Walkable、または Jump
Activatedリンクの使用可否を制御
カスタムリンクの通行
using UnityEngine;
using UnityEngine.AI;
using System.Collections;

public class CustomLinkTraversal : MonoBehaviour
{
    NavMeshAgent agent;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        agent.autoTraverseOffMeshLink = false;
    }

    void Update()
    {
        if (agent.isOnOffMeshLink) StartCoroutine(TraverseLink());
    }

    IEnumerator TraverseLink()
    {
        OffMeshLinkData linkData = agent.currentOffMeshLinkData;
        Vector3 startPos = agent.transform.position;
        Vector3 endPos = linkData.endPos + Vector3.up * agent.baseOffset;
        float elapsed = 0f, duration = 0.5f;

        while (elapsed < duration)
        {
            float t = elapsed / duration;
            agent.transform.position = Vector3.Lerp(startPos, endPos, t)
                + Vector3.up * Mathf.Sin(t * Mathf.PI) * 2f;
            elapsed += Time.deltaTime;
            yield return null;
        }
        agent.CompleteOffMeshLink();
    }
}

Unity Sentis の概要

パッケージ: com.unity.sentis (v2.1) -- 現在は Inference Engine (com.unity.ai.inference) に名称変更されています

Unity のすべてのプラットフォームで、GPU/CPU 上で ONNX モデル(opset 7-15)を実行するためのニューラルネットワーク推論ライブラリです。

基本的なワークフロー
using UnityEngine;
using Unity.Sentis;

public class MLInference : MonoBehaviour
{
    public ModelAsset modelAsset;
    Model runtimeModel;
    Worker worker;

    void Start()
    {
        runtimeModel = ModelLoader.Load(modelAsset);
        worker = new Worker(runtimeModel, BackendType.GPUCompute);
    }

    void RunInference()
    {
        Tensor<float> input = TextureConverter.ToTensor(
            Resources.Load("image") as Texture2D);
        worker.Schedule(input);
        Tensor<float> output = worker.PeekOutput() as Tensor<float>;
        input.Dispose();
    }

    void OnDestroy() { worker?.Dispose(); }
}
バックエンドの種類
バックエンドパフォーマンス備考
GPUCompute最速(GPU)SystemInfo.supportsComputeShaders を確認してください
CPU最速(CPU)WebGL では低速です(Burst から WASM にコンパイル)
GPUPixel低速コンピュートシェーダーがない場合のフォールバック

API の詳細については、skills/unity-ai-navigation/references/sentis-ml.md を参照してください。

よくある AI パターン

シンプルなステートマシン
using UnityEngine;
using UnityEngine.AI;

public enum AIState { Idle, Patrol, Chase, Attack }

public class AIStateMachine : MonoBehaviour
{
    public AIState currentState = AIState.Idle;
    public Transform[] patrolPoints;
    public float chaseRange = 10f, attackRange = 2f;
    NavMeshAgent agent;
    Transform player;
    int patrolIndex;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        player = GameObject.FindWithTag("Player").transform;
    }

    void Update()
    {
        float dist = Vector3.Distance(transform.position, player.position);
        switch (currentState)
        {
            case AIState.Idle:
                if (dist < chaseRange) currentState = AIState.Chase;
                else if (patrolPoints.Length > 0) currentState = AIState.Patrol;
                break;
            case AIState.Patrol:
                agent.SetDestination(patrolPoints[patrolIndex].position);
                if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance)
                    patrolIndex = (patrolIndex + 1) % patrolPoints.Length;
                if (dist < chaseRange) currentState = AIState.Chase;
                break;
            case AIState.Chase:
                agent.SetDestination(player.position);
                if (dist < attackRange) currentState = AIState.Attack;
                else if (dist > chaseRange * 1.5f) currentState = AIState.Patrol;
                break;
            case AIState.Attack:
                agent.isStopped = true;
                if (dist > attackRange) { agent.isStopped = false; currentState = AIState.Chase; }
                break;
        }
    }
}
ビヘイビアツリーのノード
public enum NodeState { Running, Success, Failure }

public abstract class BTNode { public abstract NodeState Evaluate(); }

public class Selector : BTNode
{
    BTNode[] children;
    public Selector(params BTNode[] children) { this.children = children; }
    public override NodeState Evaluate()
    {
        foreach (var child in children)
        {
            var result = child.Evaluate();
            if (result != NodeState.Failure) return result;
        }
        return NodeState.Failure;
    }
}

public class Sequence : BTNode
{
    BTNode[] children;
    public Sequence(params BTNode[] children) { this.children = children; }
    public override NodeState Evaluate()
    {
        foreach (var child in children)
        {
            var result = child.Evaluate();
            if (result != NodeState.Success) return result;
        }
        return NodeState.Success;
    }
}
NavMesh クエリ
using UnityEngine;
using UnityEngine.AI;

public class NavMeshQueries : MonoBehaviour
{
    public Vector3 GetNearestNavMeshPoint(Vector3 pos, float maxDist)
    {
        NavMeshHit hit;
        return NavMesh.SamplePosition(pos, out hit, maxDist, NavMesh.AllAreas)
            ? hit.position : pos;
    }

    public bool IsOnNavMesh(Vector3 pos)
    {
        NavMeshHit hit;
        return NavMesh.SamplePosition(pos, out hit, 0.1f, NavMesh.AllAreas);
    }

    public bool CanReachTarget(Vector3 start, Vector3 end)
    {
        NavMeshPath path = new NavMeshPath();
        NavMesh.CalculatePath(start, end, NavMesh.AllAreas, path);
        return path.status == NavMeshPathStatus.PathComplete;
    }

    public Vector3 GetRandomNavMeshPoint(Vector3 center, float range)
    {
        Vector3 dir = Random.insideUnitSphere * range + center;
        NavMeshHit hit;
        return NavMesh.SamplePosition(dir, out hit, range, NavMesh.AllAreas)
            ? hit.position : center;
    }
}

アンチパターン

  • 毎フレーム NavMesh をベイクする -- BuildNavMesh() は処理コストが高いため、ジオメトリが変更されたときのみ呼び出してください。差分更新には UpdateNavMesh() を使用してください。
  • pathStatus を確認しない -- 必ず agent.pathStatus を確認してください。パスが部分的、または無効な場合、エージェントは気づかれないまま動けなくなることがあります。
  • ガードなしで Update 内に移動先を設定する -- 毎フレームパスを再計算すると CPU を無駄に消費します。ターゲットが大きく移動した場合にのみ更新してください。
  • エージェントに NavMeshObstacle を付ける -- NavMeshAgent も持つ GameObject に NavMeshObstacle を追加しないでください。エージェントはすでに互いを回避します。
  • エリアマスクを忘れる -- 適切な Area Mask がないエージェントは、立ち入り制限区域を通り抜ける可能性があります。
  • すべてをカービングする -- カービングは処理コストが高いため、エージェントが自然に迂回できる障害物には、カービングを行わない障害物を使用してください。
  • NavMeshSurface がない -- NavMeshSurface がなければ NavMesh はありません。エージェントは移動しません。
  • Sentis のワーカーを破棄しない -- 必ず OnDestroy() で worker.Dispose() を呼び出してください。
  • WebGL で CPU バックエンドを使用する -- Burst が WASM にコンパイルされるため、ML 推論が非常に遅くなります。

主要 API クイックリファレンス

クラス名前空間用途
NavMeshAgentUnityEngine.AIパスファインディングと移動
NavMeshObstacleUnityEngine.AI動的な障害物
NavMeshUnityEngine.AI静的なクエリとサンプリング
NavMeshPathUnityEngine.AI計算済みパスのデータ
NavMeshHitUnityEngine.AIレイキャスト/サンプリング結果
NavMeshSurfaceUnity.AI.NavigationNavMesh のベイク
NavMeshModifierUnity.AI.Navigationオブジェクト単位のオーバーライド
NavMeshModifierVolumeUnity.AI.Navigationボリューム単位のオーバーライド
NavMeshLinkUnity.AI.Navigationサーフェスの接続
ModelAssetUnity.SentisONNX モデルの参照
ModelLoaderUnity.Sentis実行時のモデル読み込み
WorkerUnity.Sentis推論エンジン
BackendTypeUnity.SentisGPUCompute、CPU、GPUPixel
Tensor<T>Unity.Sentis入力/出力データ

関連スキル

  • unity-foundations -- GameObject、コンポーネント、シーン階層
  • unity-scripting -- C# スクリプトのパターン、MonoBehaviour のライフサイクル
  • unity-physics -- コライダー、レイキャスト、NavMesh との物理演算の統合

Additional Resources

コメント