【Unity3d学习】AR技术的简单了解

写在前面

AR简介

增强现实(Argumented Reality (AR))是一种将真实世界信息和虚拟世界信息“无缝”集成的新技术,是把原本在现实世界的一定时间空间范围内很难体验到的实体信息(视觉信息,声音,味道,触觉等),通过电脑等科学技术,模拟仿真后再叠加,将虚拟的信息应用到真实世界,被人类感官所感知,从而达到超越现实的感官体验。
混合现实(Mixed reality (MR)) 有时被称为超现实(hybrid reality),是真实和虚拟世界的合并,产生新的可视化环境,物理和数字对象实时共存且在其中交互。混合现实不仅发生在物理世界或虚拟世界中,而是融合了现实和虚拟现实,通过身临其境的技术包含增强现实和增强虚拟。
实际应用中,我们对 AR 和 MR 技术通常是不区分,简称 AR/MR 技术。

Vuforia使用

Vuforia一直是开发者最青睐的AR SDK,众多的功能以及高质量的识别技术,良好的跨平台性和兼容性,兼容目前主流的PC,Android,IOS平台。 Vuforia 引擎支持 Unity 引擎以及三个主要平台:iOS、Android 和 UWP (Windows)。所以它收到许多开发者的喜爱。

Unity内嵌的Vuforia模块

使用Unity2017以上版本就可以在安装的时候选择添加Vuforia的模块,从而能够在Unity编辑器上使用Vuforia的组件。
在这里插入图片描述
或者是从官网中下载(链接地址)相应的安装包。
在这里插入图片描述
对于2019版本,有一点坑就是需要导入相应的package,然后该包中含有一个自动执行的脚本,会将所需要安装包的链接加入到Unity2019版的包管理器中,然后自动从链接中下载所需要的资源,但是由于服务器的国外的,所以下载速度非常慢,会造成卡住不动的现象。
所以我安装了2018版的Unity来使用。

安装完成之后,需要在Unity中打开相应的设置:
在这里插入图片描述
在这里插入图片描述
然后就可以在对象树中添加相应的AR组件了:
在这里插入图片描述

使用Vuforia的AR组件

到官网(链接)注册一个账号,然后添加一个License Key。
在这里插入图片描述

然后添加数据库:
在这里插入图片描述
并且添加一张图片,作为识别的目标:
在这里插入图片描述
注意图片的识别度,星越多,越容易识别。
在这里插入图片描述
把数据库下载下来:
在这里插入图片描述

使用AR Camera组件

进入Unity,设置playsetting:
在这里插入图片描述
在这里插入图片描述

然后就可以在Unity中添加Vuforia的AR组件了:
在这里插入图片描述

添加AR Camera,删除原有的Camera。然后进行一点设置:
在这里插入图片描述

添加License和database:
在这里插入图片描述
数据库的添加通过导入之前我们下载的包来实现。

在场景中添加Image,就会在结构树中出现一个ImageTarget的对象。将准备好的模型添加在上面,并且调整一下位置:
在这里插入图片描述
在这里插入图片描述

运行,然后摄像头对着图片,就能够显示相应的模型了:
在这里插入图片描述

添加虚拟按钮

在Image Target 的 Inspecter中找到添加虚拟按钮的选项:
在这里插入图片描述

给虚拟按钮挂载一下代码:

using UnityEngine;
using Vuforia;

public class VirtualButtonEventHandler : MonoBehaviour, IVirtualButtonEventHandler {
    public GameObject vb;
    public Animator ani;

    void Start() {
        VirtualButtonBehaviour vbb = vb.GetComponent<VirtualButtonBehaviour>();
        if(vbb){
            vbb.RegisterEventHandler(this);
        }
    }

    public void OnButtonPressed(VirtualButtonBehaviour vb) {
        ani.SetTrigger("Take Off");
        ani.SetBool("onPress", true);
        Debug.Log("Pressed!");
    }

    public void OnButtonReleased(VirtualButtonBehaviour vb) {
        ani.SetTrigger("Land");
        ani.SetBool("onPress", false);
        Debug.Log("Released!");
    }
}

其中改变了模型的动画,动画状态转换图如下:
在这里插入图片描述

然后为了显示button,可以在button的位置加一个平面对象(Plane),使其能够显示在屏幕中。
触碰虚拟按钮(需要完全覆盖),就能发现模型能够动起来。
项目地址:传送门
在这里插入图片描述

AR小游戏制作

利用AR组件制作一个简单的躲避球小游戏:

玩家控制角色(天蓝色小球),向上移动(会自然下落),从而躲避冲来的障碍小球。
碰到障碍则游戏失败

首先还是一样用到Vuforia的图像数据库,这里直接用之前的龙纹图片。
然后将我们控制的角色(一个天蓝色小球)添加为ImageTarget的子对象,就能够随着图像的识别而显示出来,基本布局很简单,上面已经有过相关的实践了。
直接来游戏设计部分:
首先需要有各种障碍出现,来躲避。所以这里可以给这些障碍制成预制体,并且挂载一个控制移动的脚本:

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

public class Move : MonoBehaviour
{
    public Controller controller;
    public float speed = 9;
    Vector3 target;
    float time = 0;
    bool flag = true;
    // Start is called before the first frame update
    void Start()
    {
        GameObject tmp = GameObject.Find("Bird");
        target = 3*tmp.transform.position - 2*this.transform.position;
        controller = Director.getInstance().currentSceneController as Controller;
    }

    // Update is called once per frame
    void Update()
    {
        if (controller.getState() == 0) return;
        if (time > 5) {
            controller.addScore();
            flag = false;
            Debug.Log("score: " + controller.getScore());
            Destroy(this.gameObject);
            return;
        }
        time += Time.deltaTime;

        this.transform.position = Vector3.MoveTowards(transform.position,target,Time.deltaTime * speed);
        // this.transform.Translate(target*speed*Time.deltaTime);
        
    }
}

就是朝着我们控制目标的方向移动,但是这不是实时追踪,而只是设定一个初始目标位置的方向。并且设定一段时间后就消失。

而这里,场景控制器的作用就是不断地抛出障碍:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Controller : MonoBehaviour, SceneController, Interaction{

    public PipeFactory pipeFactory;
    public int score = 0;
    float time = 0;
    public int state = 1;
    public void loadResources() {

    }
    private void Start()
    {
        score = 0;
        pipeFactory =  this.gameObject.AddComponent<PipeFactory>();
        Director director = Director.getInstance();
        director.currentSceneController = this;
    }
    private void Update() {
        if (state == 1) {
            GameObject tmp = null;
            if (time > 3)
            {   
                tmp = pipeFactory.getPipe();
                time = 0;
            }
            else
            {
                time += Time.deltaTime;
            }
        }
            
    }

    public int getState() {
        return state;
    }

    public void addScore() {
        score += 1;
    }

    public int getScore() {
        return score;
    }
}

然后给我们的主角,添加一个刚体属性,使其能够受到重力作用。还要挂载一个控制脚本,这里暂时用鼠标点击来触发向上的动作:

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

public class Fly : MonoBehaviour
{
    public float speed = 5.5f;
    private Rigidbody rig;
    public Controller controller;
    // Start is called before the first frame update
    void Start()
    {
        rig = GetComponent<Rigidbody>();
        controller = Director.getInstance().currentSceneController as Controller;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (controller == null) {
            controller = Director.getInstance().currentSceneController as Controller;
            return;
        }
        if (controller.getState() == 0) {
            this.transform.localPosition = Vector3.zero;
            rig.useGravity = false;
            return;
        }
        if (this.transform.position.y < -5f) {
            rig.useGravity = false;
            rig.velocity = Vector3.zero;
        }
        else {
            rig.useGravity = true;
        }
        if(Input.GetButtonDown("Fire1")) {
            rig.velocity = Vector3.up * speed;
        }
    }
}

添加碰撞检测,如果碰到了障碍就游戏失败:

private void OnCollisionEnter(Collision other)
{
     Controller controller = Director.getInstance().currentSceneController as Controller;
     controller.state = 0;
     Destroy(other.gameObject);
 }

使用工厂进行障碍物的创建:

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

public class PipeFactory: MonoBehaviour{
    List<GameObject> activeList = new List<GameObject>();
    List<GameObject> freeList = new List<GameObject>();

    public GameObject getPipe() {
        GameObject pipe = null;
        GameObject img = GameObject.Find("ImageTarget");
        if (img != null) {
            if (freeList.Count > 0)
            {
                pipe = freeList[0].gameObject;
                freeList.Remove(freeList[0]);
                pipe.transform.Rotate(0,0,0);
            }
            else
            {
                pipe = Instantiate(Resources.Load<GameObject>("Prefabs/Pipe"), new Vector3(8, Random.Range(-3,3),0), Quaternion.identity);
            }
            pipe.SetActive(true);
            pipe.transform.parent = img.transform;
            float x = Random.Range(-1,1) > 0 ? 0.5333f : -0.5333f;
            pipe.transform.localPosition = new Vector3(x, Random.Range(-1f,1f),0);
        }

        
        return pipe;
    }

    public void free(GameObject pipe) {
        GameObject tmp = null;
        foreach (GameObject i in activeList)
        {
            if (pipe.GetInstanceID() == i.gameObject.GetInstanceID())
            {
                tmp = i;
                break;
            }
        }
        if (tmp != null) {
            tmp.gameObject.SetActive(false);
            freeList.Add(tmp);
            activeList.Remove(tmp);
        }
    }
}

使用虚拟按钮,添加相应的事件:
使得一直按着按钮的时候,小球会一直向上运动。

using UnityEngine;
using Vuforia;

public class VirtualButtonEventHandler : MonoBehaviour, IVirtualButtonEventHandler {
    public GameObject vb;
    public GameObject ball;

    public float speed = 7f;
    private Rigidbody rig;
    public Controller controller;
    bool isPressed = false;

    void Start() {
        VirtualButtonBehaviour vbb = vb.GetComponent<VirtualButtonBehaviour>();
        if(vbb){
            vbb.RegisterEventHandler(this);
        }
        rig = ball.GetComponent<Rigidbody>();
        controller = Director.getInstance().currentSceneController as Controller;
    }

    public void OnButtonPressed(VirtualButtonBehaviour vb) {
        if (controller == null) {
            controller = Director.getInstance().currentSceneController as Controller;
            return;
        }
        if (controller.getState() == 0) {
            return;
        }
        isPressed = true;
        Debug.Log("Pressed!");
    }

    public void OnButtonReleased(VirtualButtonBehaviour vb) {
        isPressed = false;
        Debug.Log("Released!");
    }
    private void FixedUpdate()
    {
        if (isPressed) {
            rig.velocity = Vector3.up * speed;
        }
    }
}

还可以根据情况调整button的灵敏度:
在这里插入图片描述

最终效果:
在这里插入图片描述

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值