FPS游戏之AI
最近在做策划给的一些关于FPS类型的需求,Demo基本已经成型,接下来整理并记录,高手略过,不喜勿喷!!!
一个好的AI会使游戏的可玩性大大增加,我这里只是简单的AI。
大致思路:
设置好后怪物的巡逻路径点,正常情况下,怪物处于巡逻状态,每到一个路径点会停下来张望,如果player接近怪物达到一定的距离,怪物的状态会变成追踪状态,当距离player一定距离状态会变成攻击状态,当怪物追踪到距离路径包围盒一定距离状态会转换成Back状态,回到当前路径点状态切换回巡逻状态
怪物受攻击状态过程中涉及怪物受击打动画(小坑),怪物死亡动画(后续更新)
攻击过程中player全屏掉血(后续更新)
上代码(不完整,主要思路)
//AI状态
public enum AI_State {
None,
Patrol,//巡逻
ChasingPlayer,//跟随
AimingPlayer,//
AttackingPlayer,//攻击
Attacked,//受到攻击
Back,//返回状态
Dead,//死亡
}
//敌人种类
public enum Enemy_Type {
Soldier,
}
//当前状态
public AI_State actualState = AI_State.Patrol;
private float chasingSpeed = 2f;//跟随速度
private float nomalPatrolSpeed = 2.0f;//巡逻速度
//追踪距离
private float chasingDistance = 6;
//攻击距离
private float attackDistance = 1.5f;
//最大追踪距离
private float maxChasingDistance = 22;
//路径
public FPS_WaypointsRoute waypointRoute;//路径点
private int currentWayPoint = 0;//当前路径索引
[HideInInspector]
public Transform[] waypoints;
private float timeToWait = 3.0f;//到达一个路径点停留时间
private UnityEngine.AI.NavMeshAgent agent;//导航组件
private Animator animator;
private AnimatorStateInfo info;
void Start () {
player = GameObject.FindGameObjectWithTag("Player");
agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
animator = GetComponent<Animator>();
if (player)
playerTransform = player.transform;
//设置路径
SetWaypoints();
//设置随机等待时间
SetTimeToWait();
//设置初始路径点
SetWaypoint(waypoints[0].position);
if (waypoints.Length > 0) {
finalGoal = waypoints[0].transform.position;
}
bountCenter = GetCenter(waypointRoute.transform);//所有路径点的包围盒
}
void Update () {
if (animator) {
info = animator.GetCurrentAnimatorStateInfo(0);
}
//路径包围盒距离Ai最大的距离
if (Vector3.Distance(this.transform.position, bountCenter) > maxChasingDistance)
{
actualState = AI_State.Patrol;
}
if (actualState != AI_State.Attacked) {
if (playerActualDistance > chasingDistance) {
if (lastState == AI_State.AttackingPlayer || lastState == AI_State.ChasingPlayer || lastState == AI_State.Attacked) {
actualState = AI_State.Back;
} else {
actualState = AI_State.Patrol;
}
} else if (playerActualDistance <= chasingDistance && playerActualDistance >= attackDistance) {
if (!info.IsName("Attack")) {
actualState = AI_State.ChasingPlayer;
} else {
animator.ResetTrigger("AttackT");
}
if (animator) {
animator.ResetTrigger("AttackT");
}
} else if (playerActualDistance < attackDistance) {
actualState = AI_State.AttackingPlayer;
}
} else {
FPS_Kill.Instance.UnNomalStrike = false;
if (animator) {
animator.SetBool("Idle", false);
}
if (playerActualDistance < attackDistance) {
actualState = AI_State.AttackingPlayer;
if (animator)
animator.ResetTrigger("AttackT");
} else {
actualState = AI_State.Attacked;
}
}
switch (actualState) {
case AI_State.Patrol:
if (waypoints.Length > 0) {
if (agent.remainingDistance > 0.5f && !waiting) {
agent.SetDestination(finalGoal);
if (animator) {
animator.SetBool("Idle",false);
}
} else if (!waiting && waitTimer < actualTimeToWait ) {
waiting = true;
}
if (waiting) {
if (animator) {
animator.SetBool("Idle", true);
}
StopMovement();
if (waitTimer < actualTimeToWait)
waitTimer += Time.deltaTime;
else
ChangeWaytpoint();
}
}
break;
case AI_State.ChasingPlayer:
if (animator) {
animator.SetBool("Idle", false);
}
agent.SetDestination(player.transform.position);
lastState = AI_State.ChasingPlayer;
break;
case AI_State.AttackingPlayer:
StopMovement();
LookToTarget(player.transform.position);
AttackPlayer();
lastState = AI_State.AttackingPlayer;
break;
case AI_State.Back:
agent.SetDestination(waypoints[currentWayPoint].transform.position);
bloodValue = Mathf.Lerp(bloodValue, 10, (Time.time-temp)*0.001f);
FPS_BloodStrip.Insatnce.ChangeBloodStrip(bloodValue / 10.0f, 0.0f, 1);
if (agent.remainingDistance < 0.5f) {
actualState = AI_State.Patrol;
lastState = AI_State.None;
FPS_Kill.Instance.UnNomalStrike = false;
//回去进入巡逻状态满血
GetComponent<FPS_Health>().health = 10;
FPS_BloodStrip.Insatnce.ChangeBloodStrip(10 / 10.0f, 0.0f, 1);
}
break;
case AI_State.Attacked:
agent.SetDestination(player.transform.position);
lastState = AI_State.Attacked;
break;
case AI_State.Dead:
StopMovement();
break;
}
}
public void SetWaypoints() {
if (waypointRoute) {
waypoints = new Transform[waypointRoute.waypoints.Length];
for (int i = 0; i < (waypoints.Length); i++) {
waypoints[i] = waypointRoute.waypoints[i];
}
}
}
/// <summary>
/// 停止移动
/// </summary>
void StopMovement() {
if (agent != null) {
agent.velocity = Vector3.zero;
}
}
/// <summary>
/// 巡逻等待时间
/// </summary>
void SetTimeToWait() {
actualTimeToWait = Random.Range(timeToWait * 0.75f, -timeToWait * 0.75f) + timeToWait;
}
/// <summary>
/// 更改路径点
/// </summary>
void ChangeWaytpoint() {
waiting = false;
currentWayPoint++;
if (currentWayPoint >= waypoints.Length) {
currentWayPoint = 0;
}
waitTimer = 0.0f;
SetTimeToWait();
SetWaypoint(waypoints[currentWayPoint].transform.position);
}
/// <summary>
/// 设置路径点
/// </summary>
/// <param name="Pos"></param>
void SetWaypoint(Vector3 Pos) {
SetRandomPosVar(Pos);
agent.SetDestination(finalGoal);
}
/// <summary>
/// 设置目标路径点
/// </summary>
/// <param name="goal"></param>
void SetRandomPosVar(Vector3 goal) {
finalGoal = goal + new Vector3(Random.Range(-1, 1), 0, Random.Range(-1, 1));
}