AR開發(fā)實戰(zhàn)Vuforia項目之守護森林消滅伐木工(塔防游戲)

一、主要框架

二、模型

三、關鍵代碼

Bullet

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

public class Bullet : MonoBehaviour {

    //防御塔的引用
    public GameObject tower;

    //所有敵人的引用;
    private EnemyController[] enemys;

    //開始發(fā)射子彈的距離;
    private float distance;

    //最近的敵人;
    private EnemyController nearestEnemy;

    //判斷塔與敵人的距離;
    private float dis;


    //子彈傷害值;靜態(tài)的一般公開的才方便調用
    public  static float bulletDamage;

    void Start () {


        //定義傷害值
        bulletDamage = 10f;
    }
    

    void Update () {
        //尋找敵人的方法
        //--------------------------------------------------------------

        //設置最近距離;
        distance = 500f;
        //獲取所有子物體;
        enemys = FindObjectsOfType<EnemyController>();
        //遍歷所有子物體 以獲取最近敵人;
        for (int i = 0; i < enemys.Length; i++)
        {
            //獲取兩物體間的距離
            dis = Vector3.Distance(tower.transform.position, enemys[i].transform.position);
            //判斷是否是防御距離二發(fā)射子彈;
            if (dis < distance)
            {
                distance = dis;
                nearestEnemy = enemys[i];
                Debug.Log("最近敵人");
            }

        }
        //--------------------------------------------------------------

        //判斷如果最近敵人不為空 就發(fā)射子彈;
        if (nearestEnemy!=null)
        {
           
            //子彈的位置 從塔的位置移向到敵人的位置;
            this.transform.position = Vector3.MoveTowards(this.transform.position,nearestEnemy.transform.position,10f); //參數3:移動速度;
           //塔的方向 朝向 最近敵人的位置;
           tower.transform.LookAt(nearestEnemy.transform);
            if (this.transform.position==nearestEnemy.transform.position)
            {
                //判斷子彈到達最近敵人時候 銷毀子彈
                Destroy(this.gameObject);
                Debug.Log("子彈銷毀");
                //釋放資源
                Resources.UnloadUnusedAssets();
            }
            else
            {
                Destroy(this.gameObject,1f);
            }
        }

        //如果敵人為空 那就把子彈銷毀掉,不要停在半空中;
        if (nearestEnemy==null)
        {
            Destroy(this.gameObject);
            //釋放資源
            Resources.UnloadUnusedAssets();
        }
    }
}

EnemyAnimation

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

/// <summary>
/// 控制敵人動畫
/// </summary>
public class EnemyAnimation : MonoBehaviour {

    //獲取 動畫 組件
    private Animator anim;

    //獲取EnemyController的工具狀態(tài) 避免實例化就開始攻擊;
    EnemyController enemyController;


    //播放音效
    private AudioSource mAudioSource;

    void Start () {
        //獲取敵人身上的動畫組件
        anim = this.GetComponent<Animator>();

        //獲取腳本組件;
        enemyController = this.GetComponent<EnemyController>();

        //獲取音效的音頻;
        mAudioSource = this.GetComponent<AudioSource>();
    }
    

    void Update () {

        //判斷塔銷毀的狀態(tài)
        if (TowerController.isDamage==false)
        {
            //獲取EnemyControoler腳本上的布爾值 是否可以攻擊
            if (enemyController.isAttack == true)
            {
                //設置動畫狀態(tài)的布爾值
                anim.SetBool("Attack", true); //參數1:動畫條件 參數文2:動畫值             
                anim.SetBool("Walk", true);
                anim.SetBool("Idle", false);

            
            }
           
        }
        else if (TowerController.isDamage == true)
        {          
                //設置動畫狀態(tài)的布爾值
                anim.SetBool("Attack", false); //參數1:動畫條件 參數文2:動畫值
                anim.SetBool("Walk", false);
                anim.SetBool("Idle",true);
          
        }

    }

    /// <summary>
    /// 播放砍塔的聲音 只需在動畫中插入這個事件就好,不要加括號
    /// </summary>
    public void KanTa() {
        //播放砍塔音效;
        mAudioSource.Play();
    }

}

EnemyController

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

/// <summary>
/// 敵人控制腳本
/// </summary>
public class EnemyController : MonoBehaviour {

    //防御塔的引用
    public GameObject towerPrefab;

    //敵人移動速度;
    private float speed=2f;
    //用來判斷敵人與塔的距離;
    private  float distance;

    //設置布爾值;必須是公開的,方便調用
    public  bool isAttack;

    //設置敵人的攻擊力度 設置靜態(tài)方便調用 不用實例化出來
    public static float damage=10f;

    //設置敵人的生命值;
    public  float enemyLife = 80f;


    //獲取畫布的組件以及敵人血條image;
   private  Canvas canvas;
   private  Image blood;

 

    void Start () {

        //剛開始時 不攻擊
        isAttack = false;

        //獲取畫布的組件;
        canvas = this.GetComponentInChildren<Canvas>();
        //獲取血條顯示圖片;
        blood = canvas.GetComponentInChildren<Image>();

    
    }
    
    
    void Update () {

        //只有塔還沒被摧毀的時候才執(zhí)行這個移動
        if (TowerController.isDamage==false)
        {
            //移動到防御塔
            //  this.transform.position = Vector3.MoveTowards(this.transform.position,towerPrefab.transform.position,2f); //參數1:當前位置 參數2:目標位置 參數3:移動時間
            this.transform.position = Vector3.MoveTowards(this.transform.position, towerPrefab.transform.position, speed);
            //測試
            //if (this.transform.position==towerPrefab.transform.position)
            //{
            //    Debug.Log("兵臨城下");
            //} 

            //返回2點之間的距離;
            distance = Vector3.Distance(this.transform.position, towerPrefab.transform.position);
            //判斷距離停止移動 并且播放攻擊的動畫;設置攻擊為真
            if (distance <= 120f)
            {
                speed = 0;
                isAttack = true;
              
            }
        }
    }

    /// <summary>
    ///子彈與敵人碰撞
    /// </summary>
    /// <param name="other"></param>
    private void OnTriggerEnter(Collider collider)
    {
        if (collider.gameObject.tag=="bullet")
        {
            Debug.Log("敵人被攻擊了");
            //敵人受傷害
            enemyLife -= Bullet.bulletDamage;
            //測試敵人生命值;
            Debug.Log("敵人生命值:"+enemyLife);

            //顯示血條的圖片;
            blood.fillAmount = enemyLife / 80;
            if (enemyLife<=0)
            {
                Destroy(this.gameObject);
                Debug.Log("敵人消滅了!");
              //  enemyLife = 80;
            }

        }
    }


}


MyTrackableEventHandler

using UnityEngine;

namespace Vuforia
{
    /// <summary>
    /// A custom handler that implements the ITrackableEventHandler interface.
    /// </summary>
    public class MyTrackableEventHandler : MonoBehaviour,
                                                ITrackableEventHandler
    {
        //防御塔預制體的引用
        public GameObject towerPrefab;

        //敵人的預制體的引用 數組 隨機生成
        public GameObject[] enemyPrefab;

        //敵人的位置
        // public Transform enemyPoint1;
        public Transform[] enemyPoint;


        //定時器 每隔2秒鐘就生成一個敵人
        public float timeGo = 3f;
        //用來接收輸入時間的
        private  float startTime ;
        //避免update中的方法不斷識別 定義一個標志位
        bool isFoundEnemy;
        #region PRIVATE_MEMBER_VARIABLES

        private TrackableBehaviour mTrackableBehaviour;
    
        #endregion // PRIVATE_MEMBER_VARIABLES



        #region UNTIY_MONOBEHAVIOUR_METHODS
    
        void Start()
        {
            //給時間賦值
            startTime = timeGo;

            //剛開始不可識別;
            isFoundEnemy = false;

            mTrackableBehaviour = GetComponent<TrackableBehaviour>();
            if (mTrackableBehaviour)
            {
                mTrackableBehaviour.RegisterTrackableEventHandler(this);
            }
        }

        #endregion // UNTIY_MONOBEHAVIOUR_METHODS



        #region PUBLIC_METHODS

        /// <summary>
        /// Implementation of the ITrackableEventHandler function called when the
        /// tracking state changes.
        /// </summary>
        public void OnTrackableStateChanged(
                                        TrackableBehaviour.Status previousStatus,
                                        TrackableBehaviour.Status newStatus)
        {
            if (newStatus == TrackableBehaviour.Status.DETECTED ||
                newStatus == TrackableBehaviour.Status.TRACKED ||
                newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
            {
                //事件中識別防御塔的方法;
                OnTrackingFound();
                //重新識別之后塔沒有被破壞
                TowerController.isDamage = false;
                //事件中是識別敵人的方法;
                OnTrackingEnemyFound();
            }
            else
            {
                OnTrackingLost();
            }
        }

        #endregion // PUBLIC_METHODS

        //不斷識別敵人
         void Update()
        {

            //判斷塔的狀態(tài) 只有不被銷毀的時候才實例化敵人
            if (TowerController.isDamage==false)
            {
                //時間遞減
                timeGo -= Time.deltaTime;
                //如果時間歸零并且滿足條件為真
                if (timeGo <= 0 && isFoundEnemy == true)
                {
                    OnTrackingEnemyFound();
                    //時間回到初始化值
                    timeGo = startTime;
                }

            }


        }



        #region PRIVATE_METHODS


        private void OnTrackingFound()
        {

            //識別防御塔時候實例化
            GameObject Tower = GameObject.Instantiate(towerPrefab) as GameObject;
            //設置父類
            Tower.transform.parent = this.transform;
            //設置位置
            Tower.transform.position = this.transform.position;


            ////識別敵人
            //GameObject Enemy = GameObject.Instantiate(enemyPrefab[Random.Range(0,3)]) as GameObject;
            //Enemy.transform.parent = this.transform;
            //// Enemy.transform.position = this.transform.position+new Vector3(3,0,3);  //加個位置
            ////敵人的位置
            //Enemy.transform.position = enemyPoint[Random.Range(0, 3)].position;

            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
        }

        /// <summary>
        /// 識別敵人的方法
        /// </summary>
        private void OnTrackingEnemyFound() {

            //找到了設置為真
            isFoundEnemy = true;
            //識別敵人
            GameObject Enemy = GameObject.Instantiate(enemyPrefab[(int)Random.Range(0, 3)]) as GameObject;
            Enemy.transform.parent = this.transform;
            // Enemy.transform.position = this.transform.position+new Vector3(3,0,3);  //加個位置
            //敵人的位置
            // Enemy.transform.position = enemyPoint1.position;
            //位置信息隨機
            int random = (int)Random.Range(0, 3);
            Enemy.transform.position = enemyPoint[random].position;
            //敵人的朝向 第一種方法
            //if (random == 0)
            //{
            //    Enemy.transform.rotation = Quaternion.AngleAxis(120, Vector3.up);
            //}
            //if (random==1)
            //{
            //    Enemy.transform.rotation = Quaternion.AngleAxis(240,Vector3.up);
            //}
            //if (random==2)
            //{
            //    Enemy.transform.rotation = Quaternion.AngleAxis(320,Vector3.up);
            //}
            //敵人的朝向 第二種方法
            Enemy.transform.LookAt(towerPrefab.transform);

        }

        private void OnTrackingLost()
        {
            //沒找到 設置為false
            isFoundEnemy = false;
            //防御塔沒找到的時候
            TowerController tower = GetComponentInChildren<TowerController>();
            //判斷一下沒找的時候銷毀
            if (tower!=null)
            {
                //銷毀
                DestroyImmediate(tower.gameObject);
                //釋放資源
                Resources.UnloadUnusedAssets();
            }


            //同樣 識別丟失的時候敵人銷毀
            //EnemyController enemy = GetComponentInChildren<EnemyController>();
            EnemyController[] enemy = GetComponentsInChildren<EnemyController>();
            if (enemy!=null)
            {
                //for  循環(huán) 逐個銷毀、第一種方法
                //for (int i = 0; i < enemy.Length; i++)
                //{
                //    EnemyController E = enemy[i];
                //    Destroy(E.gameObject);
                //}

                foreach (EnemyController E in enemy)
                {
                    DestroyImmediate(E.gameObject);
                    Resources.UnloadUnusedAssets();
                }

                //DestroyImmediate(enemy.gameObject);
                //Resources.UnloadUnusedAssets();
            }

            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
        }

        #endregion // PRIVATE_METHODS
    }
}

TowerController

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

public class TowerController : MonoBehaviour {


    //設置塔的生命值
    private float towerLife = 100f;

    //判斷塔是否銷毀(生命值為零時) 公開的 方便敵人停止攻擊動畫的控制
    public static bool isDamage=false;


    //獲取畫布的引用
    private Canvas canvas;

    //獲取畫布下的image;
    private Image blood;


    //子彈的預制體
    public GameObject bulletPrefab;

    //子彈生成時間 計時器
    //  private float timeGo = 0;

    //播放音效
    private AudioSource mAudioSource;

    void Start () {

        //給畫布和血條賦值;
        canvas = GetComponentInChildren<Canvas>();
        blood = canvas.GetComponentInChildren<Image>();

        //獲取子彈發(fā)射的音頻;
        mAudioSource = this.GetComponent<AudioSource>();

    }

    void Update () {
        //發(fā)射子彈的時間
        //timeGo += Time.deltaTime;
        //if (timeGo>0.3f)
        //{
        //    //執(zhí)行子彈生成的方法;
        //    CreateBullet();
        //    timeGo = 0f;
        //}
        //以上代碼是測試時用
        //--------------------------
        //點擊屏幕時調用
        if (Input.GetMouseButtonDown(0))
        {
            CreateBullet();

            //播放子彈發(fā)射音效;
            mAudioSource.Play();
        }
    }

     void OnTriggerEnter(Collider collider)
    {
        if (collider.gameObject.tag== "weapon")
        {
            towerLife -= EnemyController.damage; //調用敵人的破壞力
            //測試塔的防御值
            Debug.Log(towerLife);

            //顯示血條 畫布下的屬性
            blood.fillAmount = towerLife / 100;

            //判斷生命力小于零的時候 銷毀塔和設置為真
            if (towerLife<=0)
            {
                Destroy(this.gameObject);
                isDamage = true;
            }
        }
    }

    /// <summary>
    /// 實例化子彈的方法
    /// </summary>
    void CreateBullet() {

        //實例化子彈
        GameObject bullet = GameObject.Instantiate(bulletPrefab) as GameObject;
        //設置父類關系
        bullet.transform.parent = this.transform;
        //設置位置
        bullet.transform.position = this.transform.position+new Vector3(0,200,0);
        //設置子彈的隨機顏色
        bullet.GetComponent<MeshRenderer>().material.color = new Color(Random.Range(0f,1f),Random.Range(0f,1f),Random.Range(0f,1f));

        Debug.Log("1111111111111");

    }



}

四、展示效果

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容