ARCore丨从零到放置物体

感谢yolon3000大神关于ARCore的详细介绍,本文已获转载权限!

本文记录ARCore从零到放置物体的关键步骤,详细解析请参考博客:ARCore之路

1、导入ARCore SDK

2、删掉场景中Main CameraDirectional Light

3、将”GoogleARCore-Prefabs下的 ARCore Device 和 Environmental Light 两个预制体拖到场景,添加Event System

      ARCore Device处理所有与设备相关的事宜,更新device的位置,更新Anchor的位置,更新检测到的平面等等

      Enviromental Light则处理所有光照相关事宜,如光照强度估计,光源方向估计等等

      Event System使我们的应用能监听和处理事件信息

4、可视化平面

      a、新建DetectedPlaceGenerater空gameobject,给其添加DetectedPlaneGenerator

      b、制作Prefab平面,添加到 a 的 DetectedPlaneGenerator 脚本上

            1)、新建名为 VisualDetectedPlane 的 3DObject—Plane,必须Reset,避免实例化后生成的位置出现偏差

            2)、应用纹理:MeshRenderer—Materials选择PlaneGrid

            3)、为其添加DetectedPlaneVisualizer组件,完成预制体制作。

5、添加名为GameManager 的gameObject,为其添加 AppController 脚本。内容附在下方。其作用:

      a、进行各种错误处理

      b、管理应用生命周期:保持亮屏、息屏、变暗等

      c、放置物体

脚本内容参考文章:参考文章

enjoy!

using UnityEngine;
using GoogleARCore;

public class AppController : MonoBehaviour {

    public Camera FirstPersonCamera;    //ARCore的FirstPersonCamera摄像机
    public GameObject prefab;           //点击生成的对象预制体

    private const float mModelRotation = 180.0f;

    void Start()
    {
        //检查设备
        OnCheckDevice();
    }

    void Update()
    {
        //管理应用的生命周期
        UpdateApplicationLifecycle();

        Touch touch;
        if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
        {
            return;
        }

        //TrackableHit:保存的是发生碰撞检测时的检测到相关信息
        TrackableHit hit;
        //TrackableHitFlags:用来过滤需要进行碰撞检测的对象类型,其值可以一个,也可以是几个
        TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon | TrackableHitFlags.PlaneWithinBounds;

        //ARCore在Frame中为我们准备了四种发射射线检测物体的方法,具体参考文章
        if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
        {
            if ((hit.Trackable is DetectedPlane) && Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position, hit.Pose.rotation * Vector3.up) < 0)
            {
                Debug.Log("射线击中了DetectedPlane的背面!");
            }
            else
            {
                var prefabIns = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
                prefabIns.transform.Rotate(0, mModelRotation, 0, Space.Self);
                var anchor = hit.Trackable.CreateAnchor(hit.Pose);
                prefabIns.transform.parent = anchor.transform;
            }
        }
    }

    /// 
    /// 检查设备
    /// 
    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);
        }
    }

    /// 
    /// 管理应用的生命周期
    /// 
    private void UpdateApplicationLifecycle()
    {
        if (Session.Status != SessionStatus.Tracking)
        {
            const int lostTrackingSleepTimeout = 15;
            //Screen.sleepTimeout:一种节能设置,允许屏幕在上次激活用户交互后一段时间变暗
            Screen.sleepTimeout = lostTrackingSleepTimeout;
        }
        else
        {
            //SleepTimeout.NeverSleep:防止屏幕变暗
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
        }
    }

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

 

你可能感兴趣的:(#,ARCore)