AR开发实战Vuforia项目之PokemonGo(二、基于Lbs图块机制的实现)

一、框架视图

二、关键代码

1、AR

AR_Au

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

public class AR_Au : MonoBehaviour {

    public static AR_Au Instance; //单例模式

    private AudioSource AuS; //对声音持有引用


     void Awake()
    {
        Instance = this;//单例模式 赋值    
    }

    void Start () {

        AuS = gameObject.transform.GetComponent<AudioSource>(); //声音组件赋值
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 播放声音的事件函数
    /// </summary>
    public void BtnAuPlay() {

        AuS.Play();
    }
}

AR_UIMgr

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

public class AR_UIMgr : MonoBehaviour {

    public static AR_UIMgr Instance; //单例模式

    public Text Tx_BallNum; //储存显示精灵球数量的Text组件

    public Text Tx_FoodNum; //储存显示食物数量的Text组件

    public GameObject PnCatch; //小精灵捕捉成功的面板

    public Text InputPetName;//输入精灵名字的组件

    private void Awake()
    {
        Instance = this; //单例模式
    }

    void Start () {
        
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 返回地图按钮事件
    /// </summary>
    public void Btn_GoMapScn() {

        AR_Au.Instance.BtnAuPlay();//声音播放事件
        SceneManager.LoadScene("PKGOMain");
    }

    /// <summary>
    /// 刷新精灵球的数量事件
    /// </summary>
    public void UpdateUIBallNum() {

        Tx_BallNum.text = StaticData.BallNum.ToString();    //把精灵球数量的全集数据显示在UI中
    }


    /// <summary>
    /// 刷新食物的数量事件
    /// </summary>
    public void UpdateUIFoodNum() {

        Tx_FoodNum.text = StaticData.FoodNum.ToString(); //把食物数量的全局数据显示在UI中 
    }



    /// <summary>
    /// 显示小精灵的捕捉成功的面板
    /// </summary>
    public void Show_PnCatch() {

        PnCatch.SetActive(true);
    }


    /// <summary>
    /// 捕捉小精灵的确认按钮
    /// </summary>
    public void Btn_Yes() {

        AR_Au.Instance.BtnAuPlay();//点击按钮的特效事件

        //Debug.Log("输入的名字:"+InputPetName.text);
        string _name = InputPetName.text; //从输入框获取小精灵的名字

        int _index = StaticData.CatchingPetIndex; //从全局脚本中获取正在捕捉小精灵在预制体集合中的序号

        StaticData.AddPet(new PetSave(_name,_index));//从全局数据的小精灵列表中添加一条小精灵属性类数据

        SceneManager.LoadScene("Store_Scn"); //跳转到仓库场景
    }


    /// <summary>
    /// 放生按钮的函数
    /// </summary>
    public void Btn_GiveUp() {

        AR_Au.Instance.BtnAuPlay();//播放放生按钮的声效
        SceneManager.LoadScene("PKGOMain"); //跳回地图场景
    }


    /// <summary>
    /// 进入仓库的按钮
    /// </summary>
    public void Btn_ToStore() {

        AR_Au.Instance.BtnAuPlay(); //播放进去仓库的声效
        SceneManager.LoadScene("Store_Scn"); //进入仓库场景
    }




}

ARBallCtrl

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

public class ARBallCtrl : MonoBehaviour {


    public static ARBallCtrl Instance; //单例模式

    public Transform PosInsBall;    //储存生成精灵球的位置

    private GameObject[] balls; //储存精灵球的预制体


    private void Awake()
    {
        Instance = this; //单例模式
    }

    void Start () {

        balls = Resources.LoadAll<GameObject>("Balls");

        AR_UIMgr.Instance.UpdateUIBallNum(); //刷新精灵球的数量

        InsNewBall(); //执行测试下

        //PosInsBall.transform.parent.transform.localRotation = Quaternion.identity; //默认相机不能旋转

    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 生成精灵球
    /// </summary>
    public void InsNewBall() {

        if (StaticData.BallNum>0) //只有大于0 的情况下 才执行实例化精灵球
        {
            GameObject _ball = Instantiate(balls[0], PosInsBall.position, PosInsBall.rotation); //实例化精灵球
            _ball.transform.SetParent(PosInsBall); //设置精灵球的父级物体 为了保证发射前在屏幕的固定位置
            _ball.gameObject.AddComponent<SphereCollider>();    //给球体增加球型碰撞器
            _ball.gameObject.GetComponent<SphereCollider>().radius = 0.01f; //设置碰撞触发器半径的大小
           // _ball.gameObject.AddComponent<ARShootBall>(); //添加发射球的控制脚本

            _ball.gameObject.transform.localScale = new Vector3(25f, 25f, 25f); //原预制体不变 动态改变尺寸的大小 缩放比例

        }
       
    }



}

ARFoodCtrl

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

public class ARFoodCtrl : MonoBehaviour {

    public static ARFoodCtrl Instance;      //单例模式

    public Transform PosInsFood; //储存生成食物的位置

    private GameObject[] foods; //储存食物的预制体


    void Awake()
    {
        Instance = this;
    }


    void Start () {

        foods = Resources.LoadAll<GameObject>("Foods"); //加载所有的食物

        AR_UIMgr.Instance.UpdateUIFoodNum(); //刷新食物的数量

    }
    

    void Update () {
        
    }

    /// <summary>
    /// 生成新的食物
    /// </summary>
    public void InsNewFood() {


        if (StaticData.FoodNum>0) //如果食物大于0 的话才生成
        {

        }
    }
}

ARInsPets

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

public class ARInsPets : MonoBehaviour {

    public Transform[] traPos; //储存预制体的位置

    private GameObject[] pets;//储存所有的精灵预制体

    public Transform CameraTra;//AR摄像机的位置

    void Start () {

        pets = Resources.LoadAll<GameObject>("Pets"); //加载所有的精灵预制体

        InsPet();//生成捕捉小精灵

        checkDis(); //检查距离
    }
    



    
    void Update () {
        
    }

    /// <summary>
    /// 生成精灵
    /// </summary>
    public void InsPet() {

        int _index = Random.Range(0,traPos.Length); //随机位置

        Transform _tra = traPos[_index]; //得到随机位置

        GameObject _pet=Instantiate(pets[StaticData.CatchingPetIndex],_tra.position,_tra.rotation);   //实例化随机生成的位置上的小精灵 注意预制体数组的位置

        _pet.transform.localScale = new Vector3(0.5f,0.5f,0.5f); //生成的预制体可以缩小到0.5倍

        Debug.Log("生成小精灵的名字:::;" +_pet.name);

        _pet.transform.LookAt(new Vector3(CameraTra.position.x,_pet.transform.position.y,CameraTra.position.z)); //让生成的小精灵面朝玩家

       
    }

    /// <summary>
    /// 检查每个生成小精灵的预支点到摄像机的距离
    /// </summary>
    private void checkDis() {

        foreach (Transform pos in traPos)
        {
            float _dis = Vector3.Distance(pos.position,CameraTra.position);
            Debug.Log("检查预支点和摄像机的距离:"+_dis);
        }
    }
}

ARShootBall

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

public class ARShootBall : MonoBehaviour {

    public float FwdForce = 200f; //设置给小球向前的力的大小

    public Vector3 StanTra = new Vector3(0,1f,0);   //设置夹角的参照数值

    private bool blTouched = false;//判断手指是否触碰了精灵球的位置

    private bool blShooted = false;//判断精灵球是否可以发射

    private Vector3 startPosition; //手指滑动的起始点

    private Vector3 endPosition;    //手指滑动的终点

    private float disFick; //记录手指滑动的距离

    private Vector3 offset; //记录手指的偏移量

    private int timeFick;   //用帧数来记录手指滑动的时间

    private float speedFick;//记录滑动的速度

    private Camera camera;//记录主摄像机

    void Start () {

        camera = Camera.main; //给主摄像机赋值
    }
    

    void Update () {

        if (blTouched) //如果按在小球上 允许计算手指滑动
        {
            slip();
        }
    }

    /// <summary>
    /// 重置参数
    /// </summary>
    private void resetVari() {

        startPosition = Input.mousePosition; // 起始位置设置为手指按下的位置

        endPosition = Input.mousePosition;  //终点位置设置为手指按下的位置


    }

    /// <summary>
    /// 鼠标(手指)按下 (是否触碰到脚本挂载的物体)
    /// </summary>
    private void OnMouseDown()
    {
        if (blShooted==false) //精灵球尚未发射
        {
            blTouched = true;//允许检测手指滑动
        }
    }


    /// <summary>
    /// 计算手指滑动的距离
    /// </summary>
    private void slip() {

        timeFick += 25; //时间每帧增加25  通过测试得出的数值

        if (Input.GetMouseButtonDown(0)) //当手指按下的时候
        {
            resetVari();    //重置参数
        }

        if (Input.GetMouseButton(0)) //当手指一直持续按在屏幕的时候
        {
            endPosition = Input.mousePosition;//把手指的终点位置变量 赋值刷新为当前手指所处的位置
            offset = camera.transform.rotation * (endPosition-startPosition);//获取手指在世界坐标的偏移向量
            disFick = Vector3.Distance(startPosition,endPosition);//计算手指滑动的距离
        }

        if (Input.GetMouseButtonUp(0)) //当手指抬起的时候
        {
            speedFick = disFick / timeFick; //计算滑动的速度
            blTouched = false;//手指是否触碰到精灵球 设置为否
            timeFick = 0;//时间记录为零
            if (disFick>20&&endPosition.y-startPosition.y>0)  //r如果手指一动距离大于20 并且方向是向上滑动  防止误碰精灵球而让精灵球消失
            {
                shootBall(); //发射精灵球
            }


        }
    }


    /// <summary>
    /// 发射精灵球
    /// </summary>
    private void shootBall() {

        transform.gameObject.AddComponent<Rigidbody>(); //精灵球添加刚体
        Rigidbody _rigBall = transform.GetComponent<Rigidbody>(); //获取刚体的组件
        //_rigBall.velocity = offset * 0.003f * speedFick; //给刚体添加一个速度
        _rigBall.velocity = offset.normalized * speedFick; //normalized只获取向量的方向 没有值
        _rigBall.AddForce(camera.transform.forward*FwdForce); //给摄像机位置一个向前的力
        _rigBall.AddTorque(transform.right); //添加转矩  就是让精灵球旋转起来 有动态的感觉
        _rigBall.drag = 0.5f;//设置角阻力
        blShooted = true;//已经发射 表示在拖动精灵球 不可能有发射的效果了
        transform.parent = null; //脱离父级物体 设置父类为空 可以自由活动 免得不在偏移

        StaticData.BallNum--; //发射之后数量减一
        AR_UIMgr.Instance.UpdateUIBallNum(); //更新精灵球的数量在UI中的显示


        //ARBallCtrl.Instance.InsNewBall(); //单例 生成新的精灵球
        StartCoroutine(LateInsBall()); //开启延迟生成精灵球的函数

        Destroy(_rigBall.transform.gameObject,5f); //5秒之后销毁发射的精灵球 
        //Debug.Log("是否销毁精灵球?");

    }


    /// <summary>
    /// 延迟重新生成精灵球 
    /// </summary>
    /// <returns></returns>
    IEnumerator LateInsBall() {

        yield return new WaitForSeconds(0.2f);  //延迟0.2秒
        ARBallCtrl.Instance.InsNewBall(); //单例模式  生成心的精灵球

    }




  

}

2、Login

Login_Au

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

public class Login_Au : MonoBehaviour {

    public static Login_Au Instance; //单例模式

    private AudioSource AuS; //控制登录的声音

    void Awake()
    {
        Instance = this;//单例模式赋值
    }


    void Start () {

        AuS = gameObject.transform.GetComponent<AudioSource>();
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 播放登录声音的事件
    /// </summary>
    public void BtnAuPlay() {

        AuS.Play();
    }

}

Login_UI

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

public class Login_UI : MonoBehaviour {


    void Start () {
        
    }
    

    void Update () {
        
    }

    /// <summary>
    /// 登录地图场景
    /// </summary>
    public void Btn_ToMap() {

        Login_Au.Instance.BtnAuPlay();  //播放登录的声效
        SaveAndLoad.Load(); //静态读取全局数据的方法 在声音后面执行
        SceneManager.LoadScene("PKGOMain"); //跳转到地图场景
    }


}
3、Map
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ball_Find : MonoBehaviour {


    void Start () {
        
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 触发器检测
    /// </summary>
    /// <param name="coll"></param>
    private void OnTriggerEnter(Collider coll)
    {
        if (coll.tag=="Avatar")  //触发器 检测到标签是“Avatar” 则
        {
            UI_Mgr_02.Instance.AddBallNum(); //调用单例模式增加精灵球的数量
            Destroy(gameObject); //精灵球消失
        }
    }

}

BoyCtrl

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


/// <summary>
/// 脚本挂在主角上
/// </summary>
public class BoyCtrl : MonoBehaviour {

    private Animator mAnimator;
    //定义动画控制器


    private MoveAvatar mMoveAvatar;
    //储存角色的移动类 为了获取角色移动的状态


    void Start () {


        mAnimator = gameObject.transform.GetComponent<Animator>();
        //给动画状态机赋值 获取角色控制器的组件

        mMoveAvatar = gameObject.transform.parent.GetComponent<MoveAvatar>();
        //给移动类赋值 父类上的组件 获取移动的状态类 获取父父物体上的角色控制器的角色移动类

        
    }
    
    
    void Update () {

        if (mMoveAvatar.animationState==MoveAvatar.AvatarAnimationState.Idle) // 枚举  如果是动画状态机中角色动画状态是定义中的待机状态 则
        {

            if (!mAnimator.GetCurrentAnimatorStateInfo(0).IsName("Idle")) //如果当前播放动画不是 待机状态  则设置 触发当前的待机动画 注意前面是 非 感叹号
            {
                mAnimator.SetTrigger("Idle"); //触发动画状态机中的待机动画
            }

        }
        else if (mMoveAvatar.animationState==MoveAvatar.AvatarAnimationState.Walk) //如果是动画状态机中角色的状态是定义中的走路状态 则
        {

            if (!mAnimator.GetCurrentAnimatorStateInfo(0).IsName("Walk")) //如果当前播放的动画不是行走 则设置 触发当前行走的动画 注意加感到好 非 布尔值
            {
                mAnimator.SetTrigger("Walk"); //触发动画状态机中的走路动画
            }
           
        }
        else if (mMoveAvatar.animationState==MoveAvatar.AvatarAnimationState.Run) //如果是动画状态机中角色的状态是定义中的跑步状态 则
        {
            if (!mAnimator.GetCurrentAnimatorStateInfo(0).IsName("Run")) //如果当前播放的动画不是跑步 则设置 触发当前跑步的动画  注意非  布尔值
            {
                mAnimator.SetTrigger("Run"); //触发动画状态机中的跑步动画
            }
         
        }


    }
}

DynamicLoadEvent

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

public class DynamicLoadEvent : MonoBehaviour {


    public GameObject InsCube; //动态加载放置进地图的3D盒子

    void Start () {
        
    }
    
    
    void Update () {
        
    }


    /// <summary>
    /// 把u3d的位置转化为经纬度坐标
    /// </summary>
    public void CheckPosition()
    {
        GameObject _avatar = GameObject.FindGameObjectWithTag("Avatar"); //查到角色游戏对象

        Vector3 _avatarV3 = _avatar.transform.position; //获取游戏对象的当前位置

        Coordinates _coordinates = Coordinates.convertVectorToCoordinates(_avatarV3); //通过Vector3类型的坐标 转化成经纬度坐标

        Debug.Log("纬度 Avatar Latitude:" + _coordinates.latitude + "经度:Avatar Longitude:" + _coordinates.longitude);
        //把转化好的经纬度显示在控制台上

    }

    /// <summary>
    /// 动态加载 盒子
    /// </summary>
    public void SetCube()
    {

        Coordinates _coordinates = new Coordinates(22.5780563, 113.8649978, 0); //设置好经纬度  参数1:纬度 参数2:经度 参数3:默认为 0
        
        Vector3 _v3 = _coordinates.convertCoordinateToVector(0); //把经纬度转化成游戏中的坐标

        GameObject _cube = Instantiate(InsCube); //生成预制体盒子

        _cube.transform.position = _v3; //设置盒子的位置



    }



}

Food_Find

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

public class Food_Find : MonoBehaviour {


    void Start () {
        
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 食物触发事件
    /// </summary>
    /// <param name="coll"></param>
    private void OnTriggerEnter(Collider coll)
    {
        if (coll.tag=="Avatar") //如果检测到人的出触发器 
        {
            UI_Mgr_02.Instance.AddFoodNum();    //则调用单例模式中食物增加的方法
            Destroy(gameObject); //食物消失
        }
    }
}

InsPets

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

public class InsPets : MonoBehaviour {

    public  GameObject[] Pets;

    //游戏启动时候加载所有的精灵资源
    void Awake()
    {
        Pets = Resources.LoadAll<GameObject>("Pets"); //参数1:加载资源的类型 参数2:文件下的路径
    }

    void Start () {

        InsPet();//生成小精灵

    }
    

    void Update () {
        
    }


    /// <summary>
    /// 生成随机精灵的函数
    /// </summary>
    private void InsPet() {

        int _petIndex = Random.Range(0,Pets.Length); //随机生成一个精灵的下标序列号  序列号从0到所有小精灵的预制体数量中  随机选择

        Instantiate(Pets[_petIndex],transform.position,transform.rotation);  //实例化 生成小精灵

    }
}


InsPoint

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

public class InsPoint : MonoBehaviour {

    //公有变量首字母大写
    public GameObject Ava; //储存地图的角色

    public GameObject PrePoint; //储存事件点的预制体

    public float MinDis = 10f; //储存最小距离范围值 3米

    public float MaxDis = 50f;//储存最大距离范围 50米

    //私有变量首字母小写
    private Vector3 v3Ava; //储存当前的角色的坐标位置


    
    void Start () {
        
    }
    
    
    void Update () {
        
    }


    /// <summary>
    /// 随机生成预制体的方法 生成精灵的方法 随机一段距离然后获取距离的坐标位置信息
    /// </summary>
    public void InsPointFun() {

        Map_Au.Instance.BtnAuPlay();    //播放生成精灵的声效

        v3Ava = Ava.transform.position;//获取角色的当前位置的坐标信息

        float _dis = Random.Range(MinDis,MaxDis); //获取随机位置的信息 从最小距离到最大距离之间取一个随机值  局部变量  首写加下划线“_”

        Vector2 _pOri = Random.insideUnitCircle; //从原点(0,0)的坐标上随机获取一个任意方向的向量

        Vector2 _pNor = _pOri.normalized; //获取到向量单位的向量 只有方向,大小为1; 有方向 有值才能称为向量

        Vector3 v3Point = new Vector3(v3Ava.x+_pNor.x*_dis,2.5f,v3Ava.z+_pNor.y*_dis); //算出随机点的位置 因为值为1,所以要乘距离值 _pNor.x*_Dis随即向量的X值  _pNor.y*Dis随即向量的Y值; Y值取决要生成的游戏对象的大小

        GameObject _pointMark = GameObject.Instantiate(PrePoint,v3Point,transform.rotation); //实例化游戏物体  参数1:预制体 参数2:位置坐标信息  参数3:旋转方向为当前物体的旋转方向
    }
}

Map_Au

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

public class Map_Au : MonoBehaviour {

    public static Map_Au Instance;  //单例模式

    private AudioSource AuS; //定义声音的组件

    void Awake()
    {
        Instance = this; //单例模式     
    }

    void Start () {

        AuS = gameObject.transform.GetComponent<AudioSource>(); //声音组件的持有引用
    }
    

    void Update () {
        
    }

    /// <summary>
    /// 播放点击按钮的事件
    /// </summary>
    public void BtnAuPlay() {

        AuS.Play();

    }
}

MobileGyro

using UnityEngine;
using System.Collections;
//摄像机  陀螺仪转动
public class MobileGyro : MonoBehaviour
{
    Gyroscope gyro;
    Quaternion quatMult;
    Quaternion quatMap;
    GameObject player;
    GameObject camParent;
    void Awake()
    {
        player = GameObject.Find("Player");
        // find the current parent of the camera's transform
        Transform currentParent = transform.parent;
        // instantiate a new transform
        camParent = new GameObject("camParent");
        // match the transform to the camera position
        camParent.transform.position = transform.position;
        // make the new transform the parent of the camera transform
        transform.parent = camParent.transform;
        // make the original parent the grandparent of the camera transform
        //camParent.transform.parent = currentParent;
        // instantiate a new transform
        GameObject camGrandparent = new GameObject("camGrandParent");
        // match the transform to the camera position
        camGrandparent.transform.position = transform.position;
        // make the new transform the parent of the camera transform
        camParent.transform.parent = camGrandparent.transform;
        // make the original parent the grandparent of the camera transform
        camGrandparent.transform.parent = currentParent;

        Input.gyro.enabled=true;
        gyro = Input.gyro;

        gyro.enabled = true;
        camParent.transform.eulerAngles = new Vector3(90,-135, 0);
       //camParent.transform.eulerAngles = new Vector3(90, 0, 180);
        //quatMult = new Quaternion(0, 0, 1, 0);
        quatMult = new Quaternion(0, 0, 1, 0);
    }

    void Update()
    {

        quatMap = new Quaternion(gyro.attitude.x, gyro.attitude.y, gyro.attitude.z, gyro.attitude.w);
        Quaternion qt=quatMap * quatMult;

        transform.localRotation =qt;

    }

}

MoveEffect

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


/// <summary>
/// 浮动旋转的脚本
/// </summary>
public class MoveEffect : MonoBehaviour {

    private float radian = 0; //起始的弧度

    private float perRad = 0.03f;//弧度的变化值

    private float add = 0;  //储存位置的偏移量

    private Vector3 posOri;//储存物体生成时的真实坐标
    
    void Start () {

        posOri = transform.position;//把物体生成时的位置坐标信息记录下来
    }
    
    
    void Update () {

        //radian += perRad;//弧度不断增加

        //add = Mathf.Sin(radian); //得到弧度的偏移值

        //transform.position = posOri + new Vector3(0,add,0);//让物体不断浮动起来


        //transform.Rotate(0, Time.deltaTime * 25f,0,Space.World); //以世界坐标为旋转依据  在Y轴上进行旋转

        MoveEffeftFunc();
    }

    /// <summary>
    /// 让物体旋转上下浮动的效果
    /// </summary>
    private void MoveEffeftFunc() {

        radian += perRad;//弧度不断增加

        add = Mathf.Sin(radian); //得到弧度的偏移值

        transform.position = posOri + new Vector3(0, add, 0);//让物体不断浮动起来


        transform.Rotate(0, Time.deltaTime * 25f, 0, Space.World); //以世界坐标为旋转依据  在Y轴上进行旋转
    }
}

Pet_Find

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

public class Pet_Find : MonoBehaviour {

    public int Pet_Index;   //储存小精灵的序列号
    
    void Start () {

        if (GameObject.FindGameObjectWithTag("Avatar"))
        {
            gameObject.transform.LookAt(GameObject.FindGameObjectWithTag("Avatar").transform); //让精灵一开始朝向主角
        }
            
        
                  
    }
    

    void Update () {
        
    }


    /// <summary>
    /// 发现宠物的触发器检测
    /// </summary>
    /// <param name="coll">触发物体</param>
    private void OnTriggerEnter(Collider coll)
    {
        if (coll.tag=="Avatar") //如果检测到的物体是 主角则 设置捕捉面板的状态
        {
            UI_Mgr_02.Instance.SetIm_Catch(true); //显示捕捉面板
            UI_Mgr_02.Instance.Tx_PetName.text = StaticData.GetType(Pet_Index); //通过输入序号赋值字符串给精灵的名称
            StaticData.CatchingPetIndex = Pet_Index;//当碰到角色时 把小精灵的序列号赋值给静态数据中正要捕捉的小精灵序号
            Destroy(gameObject); //销毁精灵

        }

        if (coll.tag=="Ball")
        {
          //  Debug.Log("击中小精灵了····");
            playCatched(); //播放动画
            StartCoroutine(ShowCatchPn()); //开启延迟显示成功捕捉的画面
        }
    }

    /// <summary>
    /// 延迟显示成功捕捉面板并销毁小精灵
    /// </summary>
    /// <returns></returns>
    IEnumerator ShowCatchPn() {

        yield return new WaitForSeconds(2f);
         AR_UIMgr.Instance.Show_PnCatch();   //显示捕捉成功面板
        Destroy(transform.gameObject);//销毁小精灵本身
    }

    /// <summary>
    /// 播放被捉到的画面  私有函数首字母小写
    /// </summary>
    private void playCatched() {
        transform.GetComponent<Animator>().SetTrigger("Catched");
    }

}



PointEvent

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

/// <summary>
/// 随机生成点事件
/// </summary>
public class PointEvent : MonoBehaviour {

    // public GameObject Pet; //储存小精灵的预制体
    public GameObject[] Pets; 

    //public GameObject Ball; //储存精灵球的预制体
    public GameObject[] Balls;


    //public GameObject Food; //储存食物的预制体
    public GameObject[] Foods;


    /// <summary>
    /// 动态加载食物 和精灵球  可以考虑用asssetbundle
    /// </summary>
     void Awake()
    {
        Pets = Resources.LoadAll<GameObject>("Pets"); //参数1:加载资源的类型 参数2:文件下的路径
        Balls = Resources.LoadAll<GameObject>("Balls"); //加载所有的精灵球
        Foods = Resources.LoadAll<GameObject>("Foods"); // 加载所有的食物

    }




    void Start () {
        //申请局部变量 随机生成事件
        int _randomEvent = Random.Range(0,3);
        if (_randomEvent==0)
        {
            InsPet();
        }
        else if (_randomEvent==1)
        {
            InsBall();
        }
        else if (_randomEvent==2)
        {
            InsFood();
        }


    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 生成小精灵
    /// </summary>
    private void InsPet() {

        int _petIndex = Random.Range(0, Pets.Length); //随机生成一个精灵的下标序列号  序列号从0到所有小精灵的预制体数量中  随机选择
   
       GameObject _pet= Instantiate(Pets[_petIndex], transform.position, transform.rotation);  //实例化 生成小精灵
                                                                                               // Instantiate(Pet,transform.position,transform.rotation);

        _pet.transform.GetComponent<Pet_Find>().Pet_Index = _petIndex; //把生成的小精灵的序号传递给小精灵身上挂在的脚本
    }

    /// <summary>
    /// 生成精灵球
    /// </summary>
    private void InsBall() {

        int _ballIndex = Random.Range(0,Balls.Length);
       // Debug.Log("精灵球的下标:::::::::" + _ballIndex);
        GameObject _ball= Instantiate(Balls[_ballIndex], transform.position + new Vector3(0,5f,0),transform.rotation); //Y轴上面偏移5f距离

        //Debug.Log("精灵球的名称:::::::::" + _ball.name); //精灵球碰撞器太大·导致数量直接增加
        _ball.transform.localEulerAngles = new Vector3(-30,0,0); //围绕X轴旋转了-30度

        _ball.AddComponent<SphereCollider>(); //增加碰撞器组件
        _ball.GetComponent<SphereCollider>().isTrigger = true; //设置为触发器
        _ball.GetComponent<SphereCollider>().radius = 0.01f; //设置碰撞器的半径  注意半径的大小
        _ball.AddComponent<Rigidbody>();//添加刚体
        _ball.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;//冻结刚体上所有物理的转换效果
        _ball.AddComponent<MoveEffect>(); //添加运动特效的脚本
        _ball.AddComponent<Ball_Find>();    //添加发现精灵球的脚本

    }

    /// <summary>
    /// 生成食物
    /// </summary>
    private void InsFood() {
        int _foodIndex = Random.Range(0,Foods.Length);
       GameObject _food=Instantiate(Foods[_foodIndex],transform.position+new Vector3(0,5f,0),transform.rotation);//Y轴上偏移5f的距离

        _food.AddComponent<BoxCollider>();  //增加碰撞器组件
        _food.GetComponent<BoxCollider>().isTrigger = true; //设置为触发器
        _food.GetComponent<BoxCollider>().center = new Vector3(0,0f,0);     //设置中心点的位置
        _food.GetComponent<BoxCollider>().size = new Vector3(0.33f,0.3f,0.33f); //设置碰撞器的大小尺寸
        _food.AddComponent<Rigidbody>();//添加刚体
        _food.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll; //冻结刚体所有物体的转换
        _food.AddComponent<MoveEffect>();   //添加运动特效的脚本
        _food.AddComponent<Food_Find>();    //添加找到食物的脚本


    }





}

UI_Mgr_02

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

public class UI_Mgr_02 : MonoBehaviour {

    //单例模式
    public static UI_Mgr_02 Instance;


    public Text Tx_BallNum; //储存精灵球的数量

    public Text Tx_FoodNum; //储存食物的数量

    public GameObject Im_Catch; //储存捕捉面版


    public Text Tx_PetName; //储存精灵的名称 

     void Awake()
    {
        Instance = this;   
    }

     void Start()
    {
        Tx_BallNum.text = StaticData.BallNum.ToString();// 一开始调用全局变量中的精灵球数量在UI中的显示

        Tx_FoodNum.text = StaticData.FoodNum.ToString();    // 一开始调用全局变量中的 食物数量在UI中的显示
    }


    /// <summary>
    /// 增加精灵球的数量
    /// </summary>
    public void AddBallNum() {

        //int _num = int.Parse(Tx_BallNum.text); //将字符串转变成整型

        //_num++; //数量加加

        //Tx_BallNum.text = _num.ToString(); //文本赋值

        StaticData.BallNum++; //精灵球+1

        Tx_BallNum.text = StaticData.BallNum.ToString(); //显示精灵球数量


    }

    /// <summary>
    /// 增加食物的数量
    /// </summary>
    public void AddFoodNum() {

        //int _num = int.Parse(Tx_FoodNum.text);  //将字符串转换成整型

        //_num++; //数量加加

        //Tx_FoodNum.text = _num.ToString(); //数字转换成字符串 赋值

        StaticData.FoodNum++; //食物+1;

        Tx_FoodNum.text = StaticData.FoodNum.ToString(); //显示食物的数量


    }

    /// <summary>
    /// 设置捕捉面板的激活状态
    /// </summary>
    /// <param name="bl"></param>
    public void SetIm_Catch(bool bl) {
        Map_Au.Instance.BtnAuPlay(); //跳转的声效
        Im_Catch.SetActive(bl); //通过参数来控制面板是隐藏还是显示  参数是布尔类型
    }


    /// <summary>
    /// 跳转到Ar场景
    /// </summary>
    public void Btn_GoARScn() {
        Map_Au.Instance.BtnAuPlay(); //跳转的声效
        SceneManager.LoadScene("Ar_Scn");
    }

    /// <summary>
    /// 跳转到仓库场景
    /// </summary>
    public void Btn_ToStore() {

        Map_Au.Instance.BtnAuPlay();//跳转到仓库的声效
        SceneManager.LoadScene("Store_Scn");
    }


}

4、Pet

PetSave

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

public class PetSave  {

    private string petName = "未命名宠物";  //记录小精灵的名字

    private int petIndex = 0;//记录小精灵在对应的模型在集合中对应的序列号


    /// <summary>
    /// 精灵名字的属性
    /// </summary>
    public string PetName {
        get { return petName; }
        set { petName = value; }
    }


    /// <summary>
    /// 精灵序列号属性
    /// </summary>
    public int PetIndex
    {
        get { return petIndex; }
        set { petIndex = value; }

    }



    /// <summary>
    /// 带参数的构造函数
    /// </summary>
    /// <param name="name">精灵名字的参数</param>
    /// <param name="index">精灵序列号</param>
    public PetSave(string  name,int index) {

        PetName = name;  //名字属性赋值

        PetIndex = index;   //序列号属性赋值
    }




}

5、Static

SaveAndLoad

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

/// <summary>
/// 静态调用数据类
/// </summary>
public static class SaveAndLoad {


    /// <summary>
    /// 保存数据
    /// </summary>
    public static void Save() {

        ES3.Save<int>("BallNum", StaticData.BallNum); //保存精灵球的数量

        ES3.Save<int>("PetNum",StaticData.PetList.Count); //保存已经捕捉小精灵的数量

        //保存每个已被捕捉精灵的相关信息
        for (int i = 0; i < StaticData.PetList.Count; i++)
        {

            ES3.Save<string>("PetNm" + i.ToString(), StaticData.PetList[i].PetName);
            ES3.Save<int>("PetIndex" + i.ToString(), StaticData.PetList[i].PetIndex);
        }
    }



    /// <summary>
    /// 读取数据
    /// </summary>
    public static void Load() {
        
        if (ES3.KeyExists("BallNum")&&ES3.KeyExists("PetNum")) //先判断它是否存在
        {
            StaticData.BallNum = ES3.Load<int>("BallNum");  //读取精灵球的数量赋值给全局变量中

            int _petNum = ES3.Load<int>("PetNum"); //读取到已经捕捉到的精灵球数量

            //把存在的小精灵都赋值
            for (int i = 0; i <_petNum; i++)
            {
                string _petName = ES3.Load<string>("PetNm" + i.ToString()); //读取精灵的名称

                int _petIndex = ES3.Load<int>("PetIndex" + i.ToString()); //读取精灵的下标

                StaticData.AddPet(new PetSave(_petName,_petIndex));  //把读取到的精灵信息写入保存的类中

            }


        }

    }


}

StaticData

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 静态类
/// </summary>
public static class StaticData {

    public static int BallNum = 50; //精灵球数量的全局变量 初始化为5;

    public static int FoodNum = 20; //食物数量的全局变量 初始化为10;

    public static int CatchingPetIndex; //当前主要捕捉的小精灵在预制体集合中的序列号
    
    public static List<PetSave> PetList=new List<PetSave>(); //申请列表储存的捕捉小精灵类

    /// <summary>
    /// 捕捉小精灵的添加到集中去  向全局数据中小精灵列表添加小精灵
    /// </summary>
    /// <param name="petsave">储存小精灵的属性类</param>
    public static void AddPet(PetSave petSave) {

        PetList.Add(petSave);
    }

    /// <summary>
    /// 通过小精灵在预制体集合中的序号来获取它的精灵类型
    /// </summary>
    /// <param name="index">小精灵在集合中的序号</param>
    /// <returns>返回的类型</returns>
    public static string GetType(int index) {

        if (index == 0)
        {
            return "小熊";
        }
        else if (index == 1)
        {
            return "小牛";
        }
        else if (index == 2)
        {
            return "兔子";
        }
        else if (index == 3)
        {
            return "小鸡";
        }
        else if (index == 4)
        {
            return "老虎";
        }
        else if (index == 5)
        {
            return "猴子";
        }
        else if (index == 6)
        {
            return "白猫";
        }
        else if (index == 7)
        {
            return "狮子";
        }
        else if (index == 8)
        {
            return "企鹅";
        }
        else if (index == 9)
        {
            return "犀牛";
        }
        else
        {
            return "小黄狗";
        }


        //switch (index)
        //{
        //    case 0:
        //        return "小熊";

        //    case 1:
        //        return "小牛";

        //    case 2:
        //        return "兔子";
        //    case 3:
        //        return "小鸡";
        //    case 4:
        //        return "老虎";
        //    case 5:
        //        return "猴子";
        //    case 6:
        //        return "白猫";
        //    case 7:
        //        return "狮子";
        //    case 8:
        //        return "企鹅";
        //    case 9:
        //        return "犀牛";

        //    default:
        //        return "小黄狗";
        //}

    }

}

6、Store

Store_Au

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

public class Store_Au : MonoBehaviour {

    public static Store_Au Instance;    //单例模式

    private AudioSource AuS;    //声音组件持有的引用


     void Awake()
    {
        Instance = this; //单例模式    
    }

    void Start () {

        AuS = gameObject.transform.GetComponent<AudioSource>(); //声音组件的赋值
    }
    

    void Update () {
        
    }

    /// <summary>
    /// 点击按钮的返回声效事件
    /// </summary>
    public void BtnAuPlay() {

        AuS.Play(); //播放声效的事件
    }


}


StoreInsPet

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

public class StoreInsPet : MonoBehaviour {

    public Transform[] Pos;//储存宠物栏中小精灵的生成点

    private GameObject[] pets;//储存所有精灵的预制体

    private GameObject[] petShow = new GameObject[3]; //在仓库中显示出来的小精灵

    void Awake()
    {
        pets = Resources.LoadAll<GameObject>("Pets"); //加载所有的小精灵
    }

    void Start () {

        InsPet(); //调用此方法在仓库中的显示 
    }
    

    void Update () {
        
    }

    /// <summary>
    /// 仓库中生成小精灵的函数
    /// </summary>
    public void InsPet() {

        int _petNum = StaticData.PetList.Count;//通过全局变量储存好的精灵数量来判断 已经捕捉好的精灵数量

        //只有数量大于0 的情况下才执行如下方法
        if (_petNum>0)
        {
            for (int i = 0; i < petShow.Length; i++)
            {

                if (_petNum-1<i) //如果数量减1小于i  排列的顺序不变  返回
                {
                    return;
                }


                PetSave _petInfo = StaticData.PetList[i]; //从全局类中 获取对应的序列号中的小精灵属性   petsave类中储存的是  名字和序列号

                Instantiate(pets[_petInfo.PetIndex],Pos[i].position,Pos[i].rotation); //实例化小精灵  游戏对象就是 全局变量中对应的序列号的预制体   位置是生成的仓库位置点

                string _petNm=_petInfo.PetName;   //获取对应中精灵的名字  以致调用刷新名字的方法

                StoreUIMgr.Instance.UpDatePetNm(i,_petNm);//刷新精灵的名字

                string _petType = StaticData.GetType(_petInfo.PetIndex); //获取精灵的种类

                StoreUIMgr.Instance.UpDatePettype(i,_petType);  //刷新精灵的类型

            }

        }



    }
}

StoreUIMgr

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

public class StoreUIMgr : MonoBehaviour {


    public Text[] Tx_PetNm; //储存精灵名字的数组

    public Text[] Tx_PetType; //储存精灵类型的数组


    public static StoreUIMgr Instance; //单例模式

     void Awake()
    {
        Instance = this; //单例模式赋值  
    }

    void Start () {
        

    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 刷新小精灵的名字
    /// </summary>
    /// <param name="index">小精灵在数组中的序号</param>
    /// <param name="strNm">小精灵要显示的名字</param>
    public void UpDatePetNm(int index,string strNm) {
        Tx_PetNm[index].text = strNm;
    }



  /// <summary>
  /// 刷新小精灵的类型
  /// </summary>
  /// <param name="index">在数组中小精灵的序号</param>
  /// <param name="strType">显示小精灵的类型</param>
    public void UpDatePettype(int index,string strType) {

        Tx_PetType[index].text = strType;
    }



    /// <summary>
    /// 跳转到场景中的按钮
    /// </summary>
    public void Btn_ToMap() {

        Store_Au.Instance.BtnAuPlay(); //播放点击按钮的声效
        SceneManager.LoadScene("PKGOMain"); //跳转到主场景
    }

    /// <summary>
    /// 仓库中保存按钮
    /// </summary>
    public void Btn_Save() {

        SaveAndLoad.Save(); //保存数据的方法
    }

}

三、效果展示

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

推荐阅读更多精彩内容