ARCore⭐二、从零到放置物体

发布于:2022-12-25 ⋅ 阅读:(321) ⋅ 点赞:(0)

在这里插入图片描述

目录

🟥 项目的基础配置

🟧 平面可视化

🟨 ARCore实用脚本


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

本文目标:实现ARCore从零到放置物体。

🟥 项目的基础配置

完成如下基础配置:

  • 导入ARCore SDK
  • 删掉场景中Main Camera 和 Directional Light
  • 将”GoogleARCore-Prefabs下的 ARCore Device 和 Environmental Light 两个预制体拖到场景,添加Event System

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

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

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

🟧 平面可视化

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

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

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

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

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

🟨 ARCore实用脚本

将下方脚本添加到AppController 脚本。该脚本作用是:

  • 进行各种错误处理
  • 管理应用生命周期:保持亮屏、息屏、变暗等
  • 放置物体
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;
            }
        }
    }

    /// <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 UpdateApplicationLifecycle()
    {
        if (Session.Status != SessionStatus.Tracking)
        {
            const int lostTrackingSleepTimeout = 15;
            //Screen.sleepTimeout:一种节能设置,允许屏幕在上次激活用户交互后一段时间变暗
            Screen.sleepTimeout = lostTrackingSleepTimeout;
        }
        else
        {
            //SleepTimeout.NeverSleep:防止屏幕变暗
            Screen.sleepTimeout = SleepTimeout.NeverSleep;
        }
    }

    /// <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");
            }));
        }
    }
}

大家还有什么问题,欢迎在下方留言!


 

在这里插入图片描述


如果你有 技术的问题  项目开发

都可以加下方联系方式

和我聊一聊你的故事🧡


网站公告

今日签到

点亮在社区的每一天
去签到