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

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

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

 利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第1张图片

这里我们需要几个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 initialization
	void Start ()
    {
        m_Animator = this.GetComponent();
        //待机
        m_Animator.SetBool("Run", false);
        m_Animator.SetBool("NextAttack", false);
        enemyHasDie = false;  
    }
	
	// Update is called once per frame
	void 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().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();
        m_Animator.SetBool("Run", false);
        m_Animator.SetBool("NextAttack",false);
        enemyHasDie = false;
        totalTime = attackInterval;
    }
// Update is called once per frame
void 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().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(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 initialization
void Start ()
    {
        knightGameObj = GameObject.FindGameObjectWithTag("KnightAI");
        knightTrans = knightGameObj.transform;
        Destroy(this.gameObject, 8f);   //8s后销毁
    }
// Update is called once per frame
void 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赋给子弹,然后赋值

 利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第2张图片利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第3张图片

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

测试如下:

 没有到攻击距离的时候:

 利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第4张图片

 

向着对方移动:

 利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第5张图片

 

攻击中:

 利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第6张图片

 

死亡一个:

 利用Vuforia开发一个AR卡牌对战(二):主要代码实现_第7张图片

 

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

 

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

你可能感兴趣的:(AR)