1. 程式人生 > >Unity3d 2017.3 AI(1) 簡單的小兵

Unity3d 2017.3 AI(1) 簡單的小兵

      PS:如果你覺得這篇文章幫到了你,請頂我一下。 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyAI : MonoBehaviour
{
    //定義敵人的類別
    public enum EnemyType
    {
        Drill,//鑽頭機器人
        Flame,//噴火機器人
        Chainsaw,//電鋸機器人
    }
    //定義敵人的模式
    public enum EnemyPattern
    {
        AT,//自動
        MT,//手動
    }

    public GameObject Enemy;//繫結Enemy單位
    public GameObject Player;//繫結玩家單位
    public EnemyType ChooseEnemyType;//選擇敵人的種類
    public EnemyPattern ChooseEnemyPattern;//選擇敵人的行動模式
    public Transform PatrolA;//Enemy單位巡邏點A
    public Transform PatrolB;//Enemy單位巡邏點B
    public GameObject LaserTX;//繫結Enemy發射的鐳射特效
    public float EnemyAttackRange = 5;//Enemy的攻擊範圍
    public float EnemyMoveSpeed = 1;//暫定移動速度
    public float EnemyRotateSpeed = 10;//暫定旋轉速度
    public int ATInterval = 500;//每500幀行動一次

    private Vector3 InitialPosition;//Enemy初始位置
    private float Dis;//Enemy與玩家單位的距離
    private Vector3 target;//Enemy初始目標
    private bool ATswitch = true;//AT模式的行動開關 用於切換旋轉和移動的狀態
    private float EnemyRotateY = 0.1f;//AT狀態下的旋轉角度
    private int My_Time = 0;//旋轉開關計時器

    // Use this for initialization
    void Start()
    {
        //遊戲開始時 記錄Enemy所在位置
        InitialPosition = Enemy.transform.position;
        //遊戲開始時 為初始目標賦值
        target = PatrolA.position;
        transform.LookAt(target);
    }

    // Update is called once per frame
    void Update()
    {
        //實時記錄Enemy與玩家單位之間的距離
        Dis = Vector3.Distance(Enemy.transform.position, Player.transform.position);

        if (ChooseEnemyPattern == EnemyPattern.MT)//手動攻擊模式
        {
            //檢測玩家是否進入Enemy的攻擊範圍
            if (EnemyAttackRange > Dis)
            {
                EnemyAttack();//進入攻擊範圍 進攻姿態
            }
            else
            {
                MTEnemyPatrol();//沒有進入攻擊範圍 巡邏姿態
            }
        }
        else if (ChooseEnemyPattern == EnemyPattern.AT)//自動攻擊模式
        {
            if (EnemyAttackRange > Dis)//進入攻擊範圍 開啟攻擊
            {
                EnemyAttack();
            }
            else//未進入攻擊範圍
            {
                ATEnemyMove();//沒有進入攻擊範圍 自由移動
            }
        }
    }

    //Enemy的攻擊方法 
    void EnemyAttack()
    {
        //Enemy會注視進入範圍的玩家單位
        Enemy.transform.LookAt(Player.transform);
        //發射鐳射
        LaserTX.SetActive(true);
    }
    //Enemy的巡邏姿態 MT
    void MTEnemyPatrol()
    {
        //進入巡邏狀態時 關閉鐳射
        LaserTX.SetActive(false);
        //Enemy看向目標地點
        Enemy.transform.LookAt(target);
        //判斷Enemy與目的地的距離是否小於0.2
        if (Vector3.Distance(Enemy.transform.position, target) <= 0.2f)
        {
            if (target == PatrolA.position)//根據Enemy所處位置 為target賦值
            {
                target = PatrolB.position;
            }
            else
            {
                target = PatrolA.position;
            }
            //Enemy看向目標地點
            Enemy.transform.LookAt(target);
        }
        //Enemy以speed速度向正前方移動
        transform.Translate(Vector3.forward * Time.deltaTime * EnemyMoveSpeed);
    }
    //Enemy的自由姿態
    void ATEnemyMove()
    {
        My_Time++;//計時器
        //關閉鐳射
        LaserTX.SetActive(false);
        if (My_Time > ATInterval)//每隔固定時間改變開關的值
        {
            if (ATswitch)
            {
                ATswitch = false;
                My_Time = 0;
            }
            else
            {
                ATswitch = true;
                My_Time = 0;
                EnemyRotateY = Random.Range(-0.1f, 0.1f);//此時改變旋轉角度 隨機數
            }
        }

        if (ATswitch)
        {
            //原地旋轉
            transform.Rotate(0, EnemyRotateY, 0);
        }
        else
        {
            //向正前方位移
            transform.Translate(Vector3.forward * Time.deltaTime * EnemyMoveSpeed);
        }
        
    }
}

這是一個簡單的小兵的AI,具備兩種模式,一種是手動模式,可以指定兩點讓小兵巡邏,也可以採用自動模式,小兵會自己移動,有攻擊和移動兩種狀態,沒有使用狀態機或者行為樹,因為太簡單不需要那麼複雜的邏輯。