1.地形搭建
1.创建平台(以Cube为例),缩放至所需大小,为其添加NavMeshSurface组件。
2.设定一个新的Agent Type命名为Enemy,Enemy参数均为默认(可根据实际需要进行调整)。
3.调整NavMeshSurface参数,在Object Collection中筛选所需烘焙的地形,默认为所有物体,因为我将多个敌人巡逻平台都设置为它的子物体,故将Collect Object修改为Current Object Hierarchy。
3.1在筛选过程中,将Collect Object修改为NavMeshModifier Conponent Only是只烘焙拥有该组件的物体,修改Include Layers用于根据层级筛选物体。
4.点击最下方的Bake即可。
配置完后如图所示
2.敌人设置
1.创建敌人(以Capsule为例),缩放至所需大小,为其添加NavMeshAgent组件,调整Agent Type为Enemy。
2.为敌人添加一个空物体命名为Warning,为其添加Sphere Collider,勾选Is Trigger并调整大小作为Enemy的警戒圈,此处Radius设置为20。
3.代码编写
1.敌人状态,其他状态根据需求添加,此处只介绍移动和警戒
public enum EnemyState
{
Moving, Warning
}
EnemyState enemyState;
private void Start()
{
enemyState = EnemyState.Moving;
}
2.巡逻参数相关
NavMeshAgent agent;
Vector3 spawnPoint;
//出生点
public float movingRadius;
//巡逻半径
float varX;
float varZ;
Vector3 varPosition;
//随机位置
Vector3 presentPosition;
//当前位置
float varDistance;
//随机位置与当前位置的距离
float minDistance;
//最近距离
private void Start()
{
agent = GetComponent<NavMeshAgent>();
spawnPoint=transform.position;
}
3.获取一个随机位置
private void RandomPosition()
{
varX = UnityEngine.Random.Range(spawnPoint.x - movingRadius, spawnPoint.x + movingRadius);
varZ = UnityEngine.Random.Range(spawnPoint.z - movingRadius, spawnPoint.z + movingRadius);
varPosition = new Vector3(varX,transform.position.y,varZ);
在出生点周围半径为R的圆内获取一个随机位置
}
4.向随机位置移动,并判断距离
private void MovingState()
{
agent.isStopped = false;
varDistance = Vector3.Distance(varPosition, transform.position);
if (varDistance <= minDistance)
{
RandomPosition();
//随机新位置
agent.SetDestination(varPosition);
//开始移动
}
}
5.为Warning添加脚本判定警戒范围内是否有Player
public GameObject player;
public bool findPlayer;
private void OnTriggerStay(Collider other)
{
if (other.tag == "player")
{
player = other.gameObject;
findPlayer = true;
}
}
private void OnTriggerExit(Collider other)
{
if (other.tag == "player")
{
Debug.Log("没发现玩家");
player = null;
findPlayer = false;
}
}
6.状态判断
GameObject warning;
private void Update()
{
findPlayer = warning.GetComponent<Warning>().findPlayer;
player = warning.GetComponent<Warning>().player;
if (findPlayer)
{
enemyState = EnemyState.Warning;
}
else
{
enemyState = EnemyState.Moving;
}
}
private void FixedUpdate()
{
switch (enemyState)
{
case EnemyState.Moving:
MovingState();
break;
case EnemyState.Warning:
WarningState();
break;
}
}
private void WarningState()
{
agent.isStopped = true;
//发现Player后停止移动
canShooting = true;
//后续攻击代码根据需要编写
}
7.设置好movingRadius保存并运行即可发现敌人在所设定的平台上移动。