AR开发实战Vuforia项目之守护森林消灭伐木工(塔防游戏)

一、主要框架

二、模型

三、关键代码

Bullet

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

public class Bullet : MonoBehaviour {

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

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

    //开始发射子弹的距离;
    private float distance;

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

    //判断塔与敌人的距离;
    private float dis;


    //子弹伤害值;静态的一般公开的才方便调用
    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);
            //判断是否是防御距离二发射子弹;
            if (dis < distance)
            {
                distance = dis;
                nearestEnemy = enemys[i];
                Debug.Log("最近敌人");
            }

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

        //判断如果最近敌人不为空 就发射子弹;
        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的工具状态 避免实例化就开始攻击;
    EnemyController enemyController;


    //播放音效
    private AudioSource mAudioSource;

    void Start () {
        //获取敌人身上的动画组件
        anim = this.GetComponent<Animator>();

        //获取脚本组件;
        enemyController = this.GetComponent<EnemyController>();

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

    void Update () {

        //判断塔销毁的状态
        if (TowerController.isDamage==false)
        {
            //获取EnemyControoler脚本上的布尔值 是否可以攻击
            if (enemyController.isAttack == true)
            {
                //设置动画状态的布尔值
                anim.SetBool("Attack", true); //参数1:动画条件 参数文2:动画值             
                anim.SetBool("Walk", true);
                anim.SetBool("Idle", false);

            
            }
           
        }
        else if (TowerController.isDamage == true)
        {          
                //设置动画状态的布尔值
                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;

    //设置敌人的攻击力度 设置静态方便调用 不用实例化出来
    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 () {

        //只有塔还没被摧毁的时候才执行这个移动
        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()
        {

            //判断塔的状态 只有不被销毁的时候才实例化敌人
            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  循环 逐个销毁、第一种方法
                //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>();

        //获取子弹发射的音频;
        mAudioSource = this.GetComponent<AudioSource>();

    }

    void Update () {
        //发射子弹的时间
        //timeGo += Time.deltaTime;
        //if (timeGo>0.3f)
        //{
        //    //执行子弹生成的方法;
        //    CreateBullet();
        //    timeGo = 0f;
        //}
        //以上代码是测试时用
        //--------------------------
        //点击屏幕时调用
        if (Input.GetMouseButtonDown(0))
        {
            CreateBullet();

            //播放子弹发射音效;
            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");

    }



}

四、展示效果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容