Unity入门第六天:敌人AI,地图随机生成


\像模像样/
本篇讲述了如何使敌方坦克的进攻更加智能,以及如何生成随机的地图


敌人AI的编写

计划中敌人(银色坦克)出现在游戏的上方,通过一系列的走位最终到达基地旁并击倒心脏。所以敌人是自动走位的,不需要人为的干涉,为了实现这个设计,我们修改了原player脚本的move方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//敌人的移动
private float v;
private float h;
//改变方向的计时器
private float timeValChangeDirection = 4;
//坦克的移动方法
private void Move(){
//如果计时器大于四秒,就改变一次方向
if(timeValChangeDirection >= 4){
//从0-7八个数字中随机生成一个
int num = Random.Range(0,8);
//因为希望敌人进攻基地,所以向下走的概率调为3/8
if(num>5){
v =-1;
h = 0;
}
//左右为2/8,向上为1/8
else if(num == 0){
v =1;
h =0;
}
else if(num >0 && num <=2){
h =-1;
v =0;
}
else if(num > 2 && num<=4){
h =1;
v=0;
}
//重置计时器
timeValChangeDirection = 0;
}
else{
//计时器小于四秒就累加
timeValChangeDirection += Time.fixedDeltaTime;
}

//把Attack方法中的识别“space“, 把Move方法中的识别”w,a,s,d"删掉
//++++++++++++人工智能初步完成++++++++++++

现在的AI看起来笨笨的,经常撞墙,下一天应该会有更新

想到魂类游戏的boss们通过识别玩家与自身的距离,位置来放不同的技能,甚至还有虚晃一招,让人捉摸不透就觉得设计一个智能的boss工程量可谓很大了。


地图的生成

hierarchy新建一个GameObject起名为MapCreation,在编写完成后就可以随机生成地图,敌人了。hierarchy中只留下了MapCreation,其他都可以删除了,看起来非常整洁。

这是一张生成好之后的地图:

在不知道具体坐标的时候,可以移动玩家的坦克,并在Game界面里找到临界点。这里是(10,8), (10,-8), (-10,8), (-10,-8)

地图的生成分为:

  • 固定的基地和基地旁的砖墙生成
  • 随机的砖墙,铁墙,草,河流生成
  • 固定的玩家和敌人生成
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class MapCreation : MonoBehaviour
    {
    //用来装饰初始化地图所需物体的数组
    //0.基地,1.墙,2.障碍,3.出生效果,4.河流, 5.草, 6.空气墙
    //在"hierarchy“界面中依次拖入GameObject中
    public GameObject[] item;

    //将所有生成的位置添加进列表
    //注意List的L要大写
    private List<Vector3> itemPoistionList = new List<Vector3>();

    //在awake()中实例化,让地图的生成先于其他所有物体
    private void Awake(){
    //实例化基地
    //Quaternion.identity:当前实例化的物体无旋转角度,预制体的旋转角度是多少,实例化得到的就是多少
    CreateItem(item[0], new Vector3(0,-8,0), Quaternion.identity);
    //用墙把基地围起来
    CreateItem(item[1], new Vector3(-1,-8,0), Quaternion.identity);
    CreateItem(item[1], new Vector3(1,-8,0), Quaternion.identity);
    //懒人用for循环建造三个砖墙
    for (int i = -1; i<2; i++){
    CreateItem(item[1], new Vector3(i,-7,0), Quaternion.identity);
    }
    //实例化空气墙,防止坦克乱跑,回收子弹
    for (int i = -11; i<12; i++){
    CreateItem(item[6], new Vector3(i,9,0), Quaternion.identity);}
    for (int i = -11; i<12; i++){
    CreateItem(item[6], new Vector3(i,-9,0), Quaternion.identity);}
    for (int i = -8; i<9; i++){
    CreateItem(item[6], new Vector3(-11,i,0), Quaternion.identity);}
    for (int i = -8; i<9; i++){
    CreateItem(item[6], new Vector3(11,i,0), Quaternion.identity);}

    //初始化玩家
    GameObject go = Instantiate(item[3], new Vector3(-2, -8, 0), Quaternion.identity);
    //得到组件,并把创建玩家设置成true,即创建玩家
    go.GetComponent<Born>().createPlayer = true;


    //产生敌人
    CreateItem(item[3], new Vector3(-10, 8, 0), Quaternion.identity);
    CreateItem(item[3], new Vector3(0, 8, 0), Quaternion.identity);
    CreateItem(item[3], new Vector3(10, 8, 0), Quaternion.identity);
    //重复调用(方法名,延时几秒后调用这个方法,每隔多久调用一次)
    InvokeRepeating("CreateEnemy", 4, 5);


    //实例化地图
    for(int i = 0; i<60;i++){
    CreateItem(item[1], createRandomPosition(), Quaternion.identity);
    }

    for(int i = 0; i<20;i++){
    CreateItem(item[2], createRandomPosition(), Quaternion.identity);
    }

    for(int i = 0; i<20;i++){
    CreateItem(item[4], createRandomPosition(), Quaternion.identity);
    }

    for(int i = 0; i<20;i++){
    CreateItem(item[5], createRandomPosition(), Quaternion.identity);
    }
    }

    //让实例化物体作为MapCreation的组件出现,而不是散落在Hierarchy上
    private void CreateItem(GameObject createGameObject,Vector3 createPosition, Quaternion createRotation){
    //实例化物体
    GameObject itemGo = Instantiate(createGameObject, createPosition,createRotation);
    //将MapCreation设定为父集层
    itemGo.transform.SetParent(gameObject.transform);
    //添加进位置列表
    itemPoistionList.Add(createPosition);
    }

    //产生随机位置的方法
    public Vector3 createRandomPosition(){
    //不生成x=-10和10两列;y=-8和8两行的位置,否则坦克会被卡住(小概率)
    while (true)
    {//int类型的Random.Range()方法包括第一个数,不包括第二个数
    Vector3 createPosition = new Vector3(Random.Range(-9,10), Random.Range(-7,8), 0);
    //如果这个位置没有被生成过,则返回一个可用的随机位置,跳出循环
    if(hasThePosition(createPosition) == false){
    return createPosition;
    }
    }
    }

    //判断位置列表中是否有这个位置
    private bool hasThePosition(Vector3 createPos){
    //列表长度用.Count来表示
    for (int i=0; i < itemPoistionList.Count; i++)
    {
    if (createPos == itemPoistionList[i]){
    return true;
    }
    }
    //如果遍历完发现没有相同的位置,则返回false表示可以建立新的位置
    return false;
    }

    //产生敌人的方法
    private void CreateEnemy(){
    //敌人随机产生的位置
    int num = Random.Range(0,3);
    Vector3 enemyPos = new Vector3();
    if (num == 0){
    enemyPos = new Vector3(-10, 8, 0);
    }
    else if (num == 1){
    enemyPos = new Vector3(0, 8, 0);
    }
    else{
    enemyPos = new Vector3(10, 8, 0);
    }
    CreateItem(item[3], enemyPos, Quaternion.identity);
    }
    }

还剩下AI的更新,UI和游戏的判定就要完成了。

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2020-2024 Yangyang Cui

请我喝杯咖啡吧~

支付宝
微信