Unity NavMesh.SamplePosition 完全ガイド

広告

NavMesh上の有効な位置を取得する方法


NavMeshとは

NavMesh(ナビゲーションメッシュ)は、
「キャラクターが歩ける場所」を示した地図です。

  • 歩ける場所 → Walkable
  • 歩けない場所 → Not Walkable

NavMeshAgentは、この地図を使って移動します。


なぜ位置の補正が必要なのか

ゲームではよくこういう状況が起きます:

  • クリックした位置がNavMesh外
  • ランダム生成した座標が壁の中
  • スポーン位置が移動不可エリア

このままだと:

  • キャラが動かない
  • ワープできない
  • 不自然な挙動になる

そこで使うのが

NavMesh.SamplePosition

です。


NavMesh.SamplePositionの基本

メソッドの定義

public static bool SamplePosition(
    Vector3 sourcePosition,
    out NavMeshHit hit,
    float maxDistance,
    int areaMask
);

引数の意味

引数内容
sourcePosition基準となる位置
hit結果(NavMeshHit)
maxDistance探索する半径
areaMask対象エリア

基本コード(最も近いNavMesh位置を取得)

using UnityEngine;
using UnityEngine.AI;

public class NavMeshUtil
{
    public static Vector3 GetNearestPosition(Vector3 target, float maxDistance = 10f)
    {
        NavMeshHit hit;

        if (NavMesh.SamplePosition(target, out hit, maxDistance, NavMesh.AllAreas))
        {
            return hit.position;
        }

        Debug.LogWarning("NavMesh上に位置が見つかりません");
        return target;
    }
}

ポイント

  • true → 見つかった
  • false → 見つからない
  • hit.position → 有効な座標

実践① クリック位置を補正して移動

void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, out RaycastHit hitInfo))
        {
            NavMeshHit navHit;

            if (NavMesh.SamplePosition(hitInfo.point, out navHit, 2.0f, NavMesh.AllAreas))
            {
                transform.position = navHit.position;
            }
        }
    }
}

授業での理解ポイント

クリック位置は信用しない → 必ずNavMeshに乗せる


実践② NavMesh上にオブジェクトをスポーン

public GameObject prefab;

void Start()
{
    Vector3 randomPos = new Vector3(
        Random.Range(-10, 10),
        0,
        Random.Range(-10, 10)
    );

    NavMeshHit hit;

    if (NavMesh.SamplePosition(randomPos, out hit, 5.0f, NavMesh.AllAreas))
    {
        Instantiate(prefab, hit.position, Quaternion.identity);
    }
}

実践③ ランダムなNavMesh位置を取得

public Vector3 GetRandomPosition(float range)
{
    Vector3 random = Random.insideUnitSphere * range;
    random += transform.position;

    return NavMeshUtil.GetNearestPosition(random, range);
}

よくあるミス

maxDistanceが小さすぎる

  • 見つからない原因No.1
    → 最初は 5〜10 でOK

NavMeshをBakeしていない

  • そもそも地図がない
    → NavMeshSurface → Bake必須

空中の座標を使っている

  • y座標がずれている
    → Raycastを使うと安全

パフォーマンス注意

  • 毎フレーム呼ぶのはNG
  • Updateで連続使用は重い

対策:

  • 必要なときだけ呼ぶ
  • 結果を使い回す

まとめ

NavMesh.SamplePositionは

  • クリック補正
  • ランダム配置
  • スポーン制御

で必須の機能です。


最重要ポイント

「その座標、本当に歩ける?」を常に疑うこと


訪問数 12 回, 今日の訪問数 12回

広告

Unity

Posted by hidepon