坦克对战游戏 AI 设计
1. 游戏要求
从商店下载游戏:“Kawaii” Tank 或 其他坦克模型,构建 AI 对战坦克。具体要求
- 使用“感知-思考-行为”模型,建模 AI 坦克
- 场景中要放置一些障碍阻挡对手视线
- 坦克需要放置一个矩阵包围盒触发器,以保证 AI 坦克能使用射线探测对手方位
- AI 坦克必须在有目标条件下使用导航,并能绕过障碍。(失去目标时策略自己思考)
- 实现人机对战
让坦克变得智能一点:
- 有目标时进行导航
- 没有目标时自动锁定下一个目标
- 离目标越近速度越慢,小于20时停止
- 当与目标之间没有障碍物时才会进行射击
让坦克变得笨一点:
- 躲避障碍物的动作很慢
- 射击有误差
- 只能以固定频率发射子弹(1s)
2. 游戏素材
在游戏商店下载“Tanks! Tutorial”
自制地图后bake:
预制的地图,坦克和子弹:
在enemy,player上有碰撞器,地图上的几个比较重要的建筑也加上了碰撞器,而子弹有触发器:
enemy,player,bullet有不同的行为,他们都是刚体:
enemy和player都有作为坦克的数据类,它们都是NavMeshAgent:
3. 代码分析
- Director
导演类,单例模式
public class Director : System.Object {
private static Director _instance;
public ScenceController scence { get; set;}
public static Director getInstance() {
if (_instance == null) {
_instance = new Director ();
}
return _instance;
}
}
- tankData
坦克的数据类
public class tankData : MonoBehaviour {
public int hp; //血条
public GameObject bulletPrefab;//子弹预制
private Team team; //队伍
//设置队伍
public void setTeam(Team t){
team = t;
}
//返回队伍
public Team getTeam(){
return team;
}
}
- PublicQuote
公共引用的枚举,接口等
//队伍:红队,蓝队
public enum Team:int{Red, Blue}
//游戏模式:自动,人机
public enum Mode:int{Auto, Play}
//游戏状态:准备,游戏中,红队胜利,蓝队胜利
public enum State:int{Ready, Playing, Win, Lose}
- EventManager
事件发布器
public class EventManager: MonoBehaviour{
//坦克的破坏事件(HP降为0)
public delegate void DestroyEvent (GameObject tank);
public static event DestroyEvent destroy;
//坦克的击中事件
public delegate void HitEvent (GameObject bullet);
public static event DestroyEvent hit;
public void destroyTank(GameObject tank){
if (destroy != null) {
destroy (tank);
}
}
public void hitTank(GameObject bullet){
if (hit != null) {
hit (bullet);
}
}
}
- ScenceController
场景管理器
(1) 成员变量
public int enemiesNum = 5; //敌人的数量
public GameObject enemyPrefab; //enemy预制
public GameObject playerPrefab; //player预制
public Mode mode = Mode.Play; //游戏模式
public Material bluePrefabs; //蓝色标志材料
public Material redPrefabs; //红色标志材料
public GameObject bulletExplosion; //子弹爆炸预制
public GameObject tankExplosion; //坦克爆炸预制
//敌人初始位置
private float enemyPos_x = -80;
private float enemyPos_y = 40;
//玩家初始位置
private Vector3 playerPos = new Vector3(80, 1, -40);
private List<GameObject> teamR; //红队列表
private List<GameObject> teamB; //蓝队列表
private GameObject player; //玩家
private State state = State.Ready; //游戏状态
private float