Raycastを使用すると送信元と送信先のオブジェクト間で障害物があるかを判断する事が出来ます。
これは例えば「銃弾が壁に接触したか判断する」「敵の視界から自身が映っていないか判定する」「地面の上に乗っているか判断する」「画面をタップした際にどの位置をタップしているか判断する」等、様々な用途に使用されます。
このRaycastはPhysics(Collider)を使用した挙動を想定して書いていますが、様々な用途に使用できる関係上、多様すると用途が干渉し使いにくくなります。
なので、Navmeshが作成したRaycastで行うアプローチについてメモしておきます。
NavmeshのRaycast
NavmeshのRaycastは、指定した座標まで障害物が無い事を確認できるAPIです。
Navmeshを利用するのでRaycastを止める壁となるColliderやキャラクターに付与するColliderが不要な点や、視点が少し高い位置にあったり壁からRaycastが抜けてしまった時に判定が発生してしまうのを防ぐ点で便利です。
またNavmesh範囲内で計算する都合、「NavmeshRaycastで届く位置には地面がある」事を保障してくれると言えるかもしれません。
NavmeshのRaycastは「Navmeshの作成したメッシュ内において、直線を引いた際に線が途切れる事があるか」を判断します。
例えば下のような地形があった場合、射線上に障害物があったり、Navmesh外に始点がある場合はNavmeshは目的地まで届かないと判定します。
また段差がありNavmeshが途切れている場合も、Navmeshは届きません。そのため、段差の上で永遠と敵キャラが近接スキルを振り続けるといった事もありません。
逆に、多少の段差があってもNavmesh的に直線でつながっているならば、見えていると判定されます。
Navmesh.Raycastを使う
Navmesh.Raycastを使ってみます。
NavMeshHit hit;
if (NavMesh.Raycast (transform.position, target.position, out hit, NavMesh.AllAreas)) {
// 見えない
} else {
// 見える
}
マニュアル曰く、Navmesh.RaycastよりNavmeshAgent.Raycastの方がお勧めだそうです。理由は多分、NavmeshAgentがNavmeshのポリゴン情報を持ってるから、それを利用する分だけオーバーヘッドが少ないとかそんな感じだと思います。
NavMeshAgent agent = GetComponent<NavmeshAgent>();
NavMeshHit hit;
if (agent.Raycast (target.position, out hit)) {
// 見えない
} else {
// 見える
}