ARCore之路-APP Controller

版权声明:David Wang原创ARCore文章,仅供学习研究之用,不得用于任何商业目的,未经授权不得转载! https://blog.csdn.net/yolon3000/article/details/81914935

  现在,我们已经创建了场景并添加了必要的支持组件,但现在场景中什么也没有,本节中,我们将要编写我们的控制器,利用ARCore提供给我们的功能来检测平面,当然,这是一个循序渐进的过程,我们首先要确保设备支持ARCore,并进行一些必要的检查以便我们后续的工作的开展。本节中,我们的目标是创建一个简单的AppController,主要是进行各种错误处理。当然主要的工作还是由ARCore来提供,我们场景中的ARCore Device中主要处理两大类问题,跟踪用户手机姿态和Session管理,跟踪处理手机的类型、姿态并实时的更新他们,Session管理AR系统的状态,它也包含了Session配置与一个第一人称的摄像头。
  既然我们要编写控制器,那么肯定要用到程序语言,如今市面上少数也有几百种程序语言。当前,在AR领域,C#是最佳的编程语言,当然也还有很多如Javascript、C++、Java也都可以用来开发AR应用。我们将主要以C#作为我们的代码编写语言,而且C#也是Unity中主要的编程语言,而Unity又是广泛运用的AR开发引擎。

一、建一个C#类

  在前节中,我们创建了一个场景,现在我们开始创建一个控制器,以便来开发和测试我们的应用,我们将从头开始一步一步的创建它。首先,我们要创建一个C#类。
  在创建我们的类之前,我们先建一个文件夹来存放代码文件(这是一个非常好的习惯)。在Project ,在”Assets” 上右键选择”Create”, 然后 “Folder”,创建一个文件夹,取名叫“Scripts”,以后所有的代码文件我们都放在这个文件夹里。

这里写图片描述

  在我们创建的“Scripts”文件夹上右键选择”Create”, 然后 “C# Scripts”,取名叫AppController.cs
这里写图片描述

  好了,现在我们创建了AppController类,双击AppController.cs会在 IDE (integrated development environment) 中打开这个类,IDE可以在Edit->Preferences->External Tools->External Script Editor 中设置,默认是monodevelop,我们使用Visual Studio 2015来开发。

二、编写控制器

  在打开的代码编辑器中,默认已经有一部分代码。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AppController : MonoBehaviour {
    // Use this for initialization
    void Start () {     
    }   
    // Update is called once per frame
    void Update () {        
    }
}

  Start()方法会在挂载脚本的物体开始时执行一次,而Update ()方法则会在每帧都更新。首先,我们添加上ARCore的命名空间。
  using GoogleARCore;
  添加这个命名空间后,我们就能使用Google ARCore SDK提供的功能了。

这里写图片描述

  代码第4行是定义了一个类,这个类继承自MonoBehaviour,不用太关心这个,大部分的Unity类都会继承自这个类,这个基类包含了很多Unity独特的方法和功能。
  如前所述,Start()方法会在挂载脚本的物体开始时执行一次,所以在这里我们可以将设备检查工作的代码写在这里,为了更好的管理我们的代码,我们另建一个方法专门负责设备检查工作,例如让用户授权摄像头的使用、弹出检查结果提示、遇到错误退出等等,使我们的AR应用更友好和更健壮。我们新建一个方法OnCheckDevice()。

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

public class AppController : MonoBehaviour {

    // Use this for initialization
    void Start () {
        OnCheckDevice();
    }

    // Update is called once per frame
    void Update () {

    }
    /// <summary>
    /// 检查设备
    /// </summary>
    private void OnCheckDevice()
    {
        if(Session.Status == SessionStatus.ErrorSessionConfigurationNotSupported)
        {
            ShowAndroidToastMessage("ARCore在本机上不受支持或配置错误!");
            Invoke("DoQuit", 0.5f);
        }
        else if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
        {
            ShowAndroidToastMessage("AR应用的运行需要使用摄像头,现无法获取到摄像头授权信息,请允许使用摄像头!");
            Invoke("DoQuit", 0.5f);
        }
        else if (Session.Status.IsError())
        {
            ShowAndroidToastMessage("ARCore运行时出现错误,请重新启动本程序!");
            Invoke("DoQuit", 0.5f);
        }
    }
    /// <summary>
    /// 退出程序
    /// </summary>
    private void DoQuit()
    {
        Application.Quit();
    }
    /// <summary>
    /// 弹出信息提示
    /// </summary>
    /// <param name="message">要弹出的信息</param>
    private void ShowAndroidToastMessage(string message)
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        if (unityActivity != null)
        {
            AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
            unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
            {
                AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,message, 0);
                toastObject.Call("show");
            }));
        }
    }
}

  OnCheckDevice()方法中,我们首先检查手机设备时否支持ARCore,然后检查是否获取到摄像头的授权,最后再确认一下有没有错误发生。在本方法中,我们ShowAndroidToastMessage()弹出检查中需要让用户知道的信息,如果应用不能再进行下去,我们则使用DoQuit()方法主动退出应用。
  ShowAndroidToastMessage()方法主要功能就是在用户屏幕上显示信息。
  在Update()中,我们将开始我们应用主流程,同样为了更清晰的管理我们的应用流程,我们另建一个方法来管理应用的生命周期。我们新建一个方法UpdateApplicationLifecycle()。在UpdateApplicationLifecycle()中,我们主要做两件事,一件事是检查当前设备是否是处于有效跟踪状态,如果当前设备目前不是正在跟踪,那么我们让应用休眠一小段时间再检查,如果当前设备目前正处于有效跟踪状态,那么我则不要让应用休眠,而是一直跟踪用户设备。当然,如果当前应用处于正在退出状态,那我们则不再进行下一步的操作,如果应用正常,那我们则进入到应用的主处理环节中。具体代码如下(注意新加了一个私有变量mIsQuitting,用来标识当前应用程序状态):

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

public class AppController : MonoBehaviour {

    private bool mIsQuitting = false;
    // Use this for initialization
    void Start () {
        OnCheckDevice();
    }

    // Update is called once per frame
    void Update () {
        UpdateApplicationLifecycle();

    }
    /// <summary>
    /// 检查设备
    /// </summary>
    private void OnCheckDevice()
    {
        if(Session.Status == SessionStatus.ErrorSessionConfigurationNotSupported)
        {
            ShowAndroidToastMessage("ARCore在本机上不受支持或配置错误!");
            mIsQuitting = true;
            Invoke("DoQuit", 0.5f);
        }
        else if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
        {
            ShowAndroidToastMessage("AR应用的运行需要使用摄像头,现无法获取到摄像头授权信息,请允许使用摄像头!");
            mIsQuitting = true;
            Invoke("DoQuit", 0.5f);
        }
        else if (Session.Status.IsError())
        {
            ShowAndroidToastMessage("ARCore运行时出现错误,请重新启动本程序!");
            mIsQuitting = true;
            Invoke("DoQuit", 0.5f);
        }
    }
    /// <summary>
    /// 管理应用的生命周期
    /// </summary>
    private void UpdateApplicationLifecycle()
    {
        if (Session.Status != SessionStatus.Tracking)
        {
            const int lostTrackingSleepTimeout = 15;
            Screen.sleepTimeout = lostTrackingSleepTimeout;
        }
        else
        {
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
        }

        if (mIsQuitting)
        {
            return;
        }
    }
    /// <summary>
    /// 退出程序
    /// </summary>
    private void DoQuit()
    {
        Application.Quit();
    }
    /// <summary>
    /// 弹出信息提示
    /// </summary>
    /// <param name="message">要弹出的信息</param>
    private void ShowAndroidToastMessage(string message)
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        if (unityActivity != null)
        {
            AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
            unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
            {
                AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,message, 0);
                toastObject.Call("show");
            }));
        }
    }
}

  至此,我们已经利用ARCore提供的功能搭建了我们的应用框架,下节我们将开始做平面检测及在合适的位置放置我们的模型。

猜你喜欢

转载自blog.csdn.net/yolon3000/article/details/81914935