プレイヤーを囲うようにナビメッシュ上に敵を配置する方法を考えてみました。
ナビメッシュ上に予め空のゲームオブジェクトをたくさん配置しておいて、その中からプレイヤーとの距離によって選ばれたものと同じ位置に敵を出現させることもできますが、空のオブジェクトを置くのが面倒です。
別の方法として、プレイヤー(緑色のCube)から8方向へ伸ばした場所(青いSphere)に敵を配置しようと思っても、そこがナビメッシュ上でないかもしれません。
そこで、NavMesh.SamplePositionを使って、8方向へ伸ばした点から最も違いナビメッシュ上の点を探して、そこに敵(赤いSphere)を配置しました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NavMeshTestScript : MonoBehaviour
{
[SerializeField] float dist = 20f;
[SerializeField] GameObject sphere;
[SerializeField] GameObject sphere2;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// 8方向のそれぞれの点から最も違い場所に配置
if (Input.GetKeyDown(KeyCode.Q))
{
NavMeshHit hit2;
// 前
Instantiate(sphere2, transform.forward * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(transform.forward * dist + transform.position, out hit2, 30f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 右ななめ前
Instantiate(sphere2, Vector3.Normalize(transform.forward + transform.right) * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(Vector3.Normalize(transform.forward + transform.right) * dist + transform.position, out hit2, 10f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 右
Instantiate(sphere2, transform.right * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(transform.right * dist + transform.position, out hit2, 30f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 右ななめ後ろ
Instantiate(sphere2, Vector3.Normalize(-transform.forward + transform.right) * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(Vector3.Normalize(-transform.forward + transform.right) * dist + transform.position, out hit2, 10f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 後ろ
Instantiate(sphere2, -transform.forward * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(-transform.forward * dist + transform.position, out hit2, 30f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 左ななめ後ろ
Instantiate(sphere2, Vector3.Normalize(-transform.forward + -transform.right) * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(Vector3.Normalize(-transform.forward + -transform.right) * dist + transform.position, out hit2, 10f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 左
Instantiate(sphere2, -transform.right * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(-transform.right * dist + transform.position, out hit2, 30f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
// 左ななめ前
Instantiate(sphere2, Vector3.Normalize(transform.forward + -transform.right) * dist + transform.position, sphere.transform.rotation);
if (NavMesh.SamplePosition(Vector3.Normalize(transform.forward + -transform.right) * dist + transform.position, out hit2, 10f, NavMesh.AllAreas))
{
Instantiate(sphere, hit2.position, sphere.transform.rotation);
}
}
}
}
8つの方向に同じ処理をしています。青いSphereはCubeと同じ高さの円上にあり、赤いSphereはナビメッシュ上にあります。
赤いSphereが青いSphereの真下にある場合もありますが、ナビメッシュ上に来るように移動されて横にそれているものもあります。
ほとんどの青い球が真下にナビメッシュの無い位置に作られていました。
球ごとにプレイヤーからの距離を変えるともっと自然な配置になると思います。次は、すでに敵がいくつか配置されているときに、まだ敵がいない方向だけに新しい敵を配置してみます。