利用Vuforia开发一个AR卡牌对战(二):主要代码实现

来源:互联网 发布:linux wlan0 切换essid 编辑:程序博客网 时间:2024/05/22 07:04

Vuforia开发AR卡牌对战游戏(二):实现

接着上一篇,我们再继续实现我们的卡牌对战游戏,上一次忘记了将血条的样式改为水平的Filed样式

 

这里我们需要几个TagKnightAIRemoteAIKnightWeapenRemoteBullet,分别给到近战,远程,近战的武器,远程的子弹上。

由于我们有两个角色,一个远程一个近战,所以我们要写两个脚本。

首先写近战的脚本:KnightCtrl,先说一下大致思路:近战角色有血量,要获得自身血条的引用,自己在被子弹击中时会减血,还需要判断敌人是否死亡,敌人死亡需要嘲讽,自己是否死亡;需要每帧去获得远程敌人的引用(因为不知道啥时候会识别到敌人识别图,所以不能在Start中获得),到了一定的距离可以向着敌人移动,到了攻击范围就去攻击敌人。下面是主要代码和注释:

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class KnightCtrl : MonoBehaviour{    public float m_Life = 100f; //血量    public float sightRange = 20f;  //视野范围,到了视野范围就向着对方移动    public float attackRange = 2f;  //攻击范围    public Image bloodImage; //血条    public static float weaponDamage = 20f;  //自己的武器伤害值    private Animator m_Animator;//动画机    private bool enemyHasDie;   //敌人是否死亡// Use this for initializationvoid Start ()    {        m_Animator = this.GetComponent<Animator>();        //待机        m_Animator.SetBool("Run", false);        m_Animator.SetBool("NextAttack", false);        enemyHasDie = false;      }// Update is called once per framevoid Update ()    {        GameObject remoteEnemy = GameObject.FindGameObjectWithTag("RemoteAI");        if (remoteEnemy != null && !enemyHasDie && m_Life > 0f) //识别图加载出来后而且敌人没有死而且自己还活着        {            float dis = Vector3.Distance(this.transform.position, remoteEnemy.transform.position);            Debug.Log(dis);            if (dis < sightRange)  //如果在视野范围之内            {                if (dis > attackRange)  //如果在攻击范围之外,就向着目标移动                {                    //向着敌人移动                    m_Animator.SetBool("Run", true);                    m_Animator.SetBool("NextAttack", false);                    this.transform.position = Vector3.MoveTowards(this.transform.position, remoteEnemy.transform.position, 0.1f);                    this.transform.LookAt(remoteEnemy.transform);                }                else //到了攻击范围,攻击                {                    m_Animator.SetBool("Run", false);                    m_Animator.SetBool("NextAttack", true);                    if (remoteEnemy.GetComponent<RemoteCtrl>().m_Life <= 0f) //获得远程人物的RemoteCtrl组件中的生命值,如果把对面打死了                    {                        enemyHasDie = true;                        m_Animator.SetTrigger("Raise Dead"); //嘲讽                        //待机                        m_Animator.SetBool("Run", false);                        m_Animator.SetBool("NextAttack", false);                    }                }            }        }}    void OnTriggerEnter(Collider other)    {        if (other.gameObject.tag == "RemoteBullet") //如果打来的是子弹        {            this.m_Life -= Bullet_R.bulletDam;  //子弹伤害            bloodImage.fillAmount = m_Life / 100f;            Destroy(other.gameObject);        }        if ( m_Life <= 0f) //如果被打死了        {            m_Animator.SetTrigger("Die");            Destroy(this.gameObject, 5f); //5s后销毁        }    }}


 

然后是远程的脚本RemoteCtrl,思路和上面相似,只不过多了一个开火的位置和动态生成子弹:

using System;using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI; public class RemoteCtrl :MonoBehaviour{    public float m_Life = 100f;//血量    public float sightRange = 20f;  //视野范围,到了视野范围就向着对方移动    public float attackRange = 5f;  //攻击范围    public float attackInterval = 1f;  //攻击间隔    public Image bloodImage;//血条    public Transform fireTrans;//开火位置    public GameObject bulletPerfab;//子弹的预制件     private Animator m_Animator;//动画机    private bool enemyHasDie;   //敌人是否死亡    private float totalTime;  //子弹的生成间隔     // Use this for initialization    void Start ()    {        m_Animator = this.GetComponent<Animator>();        m_Animator.SetBool("Run", false);        m_Animator.SetBool("NextAttack",false);        enemyHasDie = false;        totalTime = attackInterval;    }// Update is called once per framevoid Update ()    {        GameObject knightEnemy = GameObject.FindGameObjectWithTag("KnightAI");        if (knightEnemy != null && !enemyHasDie && m_Life > 0f)        {            float dis = Vector3.Distance(this.transform.position, knightEnemy.transform.position);            if (dis < sightRange) //如果在视野范围之内            {                if (dis > attackRange)//如果在攻击范围之外                {                    //向着敌人移动                    m_Animator.SetBool("Run",true);                    m_Animator.SetBool("NextAttack",false);                    this.transform.position =Vector3.MoveTowards(this.transform.position, knightEnemy.transform.position, 0.1f);                    this.transform.LookAt(knightEnemy.transform);                    totalTime = attackInterval;                }                else   //到了开火位置                {                    if (totalTime >= attackInterval)                    {                        m_Animator.SetBool("NextAttack",true);                        GenerateBullet(); //生成子弹                        totalTime = 0f;                        m_Animator.SetBool("NextAttack",false);                    }                     totalTime += Time.deltaTime;  //更新总时间                     if (knightEnemy.GetComponent<KnightCtrl>().m_Life <= 0f)                    {                        //如果敌人死了                        enemyHasDie = true;                        m_Animator.SetTrigger("Raise Dead");                        //待机                        m_Animator.SetBool("Run",false);                        m_Animator.SetBool("NextAttack",false);                     }                 }             }         } }     void GenerateBullet()    {        GameObject bulletObj = Instantiate<GameObject>(bulletPerfab);        bulletObj.transform.position = fireTrans.position; //在开火位置生成    }     void OnTriggerEnter(Collider other)    {        if (other.gameObject.tag == "KnightWeapen") //如果近战的武器攻击我了        {            this.m_Life -= KnightCtrl.weaponDamage;  //子弹伤害            bloodImage.fillAmount = m_Life / 100f;        }         if (m_Life <= 0f) //如果被打死了        {            m_Animator.SetTrigger("Die");            Destroy(this.gameObject, 5f);//5s后销毁        }     }}


接下来在写一个子弹的脚本Bullet_R,由于我们是追踪的子弹,所以脚本大致是:

using System.Collections;using System.Collections.Generic;using UnityEngine; public class Bullet_R :MonoBehaviour{    public static float bulletDam = 20f;     private GameObject knightGameObj;    private Transform knightTrans; // Use this for initializationvoid Start ()    {        knightGameObj = GameObject.FindGameObjectWithTag("KnightAI");        knightTrans = knightGameObj.transform;        Destroy(this.gameObject, 8f);   //8s后销毁    }// Update is called once per framevoid Update ()    {        if (knightGameObj != null)        {            //射击            this.transform.position = Vector3.MoveTowards(this.transform.position, knightTrans.position, 5f);        }    }} 


把所有的脚本都写好后,我们再在My_DefaultTrackableEventHandler2中修改脚本,这次在识别到后让他动态加载,丢失后销毁:

添加 public GameObject knightOrRemotePerfab;//动态加载的预制件

private GameObject knightOrRemoteObj;  //加载的GameObject的引用

修改两个方法:


 //识别到的时候

        //动态加载

        private void OnTrackingFound()

        {

            //动态加载

            knightOrRemoteObj = Instantiate<GameObject>(knightOrRemotePerfab);

            knightOrRemoteObj.transform.parent = this.transform;

            knightOrRemoteObj.transform.position = this.transform.position + this.transform.up * 2f;

 

        }

 

        //识别丢失的时候

        //销毁

        private void OnTrackingLost()

        {

            if (knightOrRemoteObj != null)

            {

                Destroy(knightOrRemoteObj);

            }

 

 }



OK,这样就差不多了,然后我们再在远程的人物身上加一个开获得位置。

然后把KnightCtrl赋给近战,RemoteCtrl付给远程,Bullet_R赋给子弹,然后赋值

 

最后将近战和远程的的人物全部弄成预制件(拖到世界空间下再Apply),然后在ImageTarget下赋值这几个预制件。具体参数需要自己调整

测试如下:

 没有到攻击距离的时候:

 

 

向着对方移动:

 

 

攻击中:

 

 

死亡一个:

 

 

基本功能已经实现了,具体的一些细节啥的还是需要细化,基本的AR卡牌对战框架就是这样。

 

本文内容部分参考自Think加速想象力出版的《ARVR开发实战》教程,更多学习资料也请关注www.arvrthink.com

阅读全文
0 0
原创粉丝点击