Unity ARKit 学习(代码分析了解常用API 分析案例 )

最近因为做的几个项目需要用的ARKit 就整理下学习的

Unity ARKit Plugin 插件下载

判断设备是否支持ARKit

//方法1
ARKitSessionConfiguration configuration = new ARKitSessionConfiguration();
        Debug.Log(configuration.IsSupported.ToString());

//方法2 
       ARKitWorldTrackingSessionConfiguration configuration2 = new ARKitWorldTrackingSessionConfiguration();
        Debug.Log(configuration2.IsSupported.ToString());

Remote 相关

在开发过程中可用ARKitRemote 发布到真机和mac 调试 如果不会发布ios 可查看之前的一片文章 Unity测试发布iOS

打包发布到 ios  移动端运行app 后mac

这样就可以通过无线 每次手机运行这个程序和电脑远程调试了

在Remote 测试时会报错 这是插件的问题我们可以修改UnityARCameraManager 脚本

这样错误就解决了


启动相机


开启检测

相机添加插件中 UnityARCameraManager  脚本并把相机拖拽到脚本变量

UnityARGeneratePlane 用于检测到平面时现实的平面

PointCloudParticleExample 用于在检测时显示的点云


using UnityEngine;
using UnityEngine.XR.iOS;

public class ARSessionController : MonoBehaviour {
    private UnityARSessionNativeInterface m_session;

	// Use this for initialization
	void Start () {
        m_session = UnityARSessionNativeInterface.GetARSessionNativeInterface();

		
	}


	/// <summary>
    /// 开启检测
    /// </summary>
    public void onRunClick(){
        m_session.Run();  //默认配置运行

    }
	/// <summary>
	/// 暂停检测
	/// </summary>
	public void OnPauseClick(){
		m_session.Pause();
	}

    /// <summary>
    /// 重制并开启追踪检测
    /// </summary>
    public void ResetAndRun(){
        
        ARKitWorldTrackingSessionConfiguration configuration = new ARKitWorldTrackingSessionConfiguration();
        configuration.alignment = UnityARAlignment.UnityARAlignmentCamera;  //检测类型
        configuration.planeDetection = UnityARPlaneDetection.Horizontal;  //平面类型
        configuration.enableLightEstimation = true;  //光照信息
        configuration.getPointCloudData = true;   //点云
        
        //m_session.RunWithConfig(configuration);
        
        m_session.RunWithConfigAndOptions(configuration, UnityARSessionRunOption.ARSessionRunOptionResetTracking); //重制追踪
        
        
    }
    /// <summary>
    /// 移除并开启追踪检测
    /// </summary>
    public void  RemoveAndRun(){
        
        ARKitWorldTrackingSessionConfiguration configuration = new ARKitWorldTrackingSessionConfiguration();
        configuration.alignment = UnityARAlignment.UnityARAlignmentGravity;  //检测类型
        configuration.planeDetection = UnityARPlaneDetection.Horizontal;  //平面类型
        configuration.enableLightEstimation = true;  //光照信息
        configuration.getPointCloudData = true;   //点云
        
        //m_session.RunWithConfig(configuration);
      
        m_session.RunWithConfigAndOptions(configuration, UnityARSessionRunOption.ARSessionRunOptionRemoveExistingAnchors); //移除之前的平面

    }
    /// <summary>
    /// 重制并关闭检测
    /// </summary>
    public void ResetAndClose(){

        ARKitWorldTrackingSessionConfiguration configuration = new ARKitWorldTrackingSessionConfiguration();
        configuration.alignment = UnityARAlignment.UnityARAlignmentGravity;  //检测类型
        configuration.planeDetection = UnityARPlaneDetection.None;  //平面类型
        configuration.enableLightEstimation = true;  //光照信息
        configuration.getPointCloudData = false;   //点云

        //m_session.RunWithConfig(configuration);

        m_session.RunWithConfigAndOptions(configuration, UnityARSessionRunOption.ARSessionRunOptionResetTracking); //重制之前的平面

    }
    /// <summary>
    /// 移除并关闭检测
    /// </summary>
    public void RemoveAndClose()
    {

        ARKitWorldTrackingSessionConfiguration configuration = new ARKitWorldTrackingSessionConfiguration();
        configuration.alignment = UnityARAlignment.UnityARAlignmentGravity;  //检测类型
        configuration.planeDetection = UnityARPlaneDetection.None;  //平面类型
        configuration.enableLightEstimation = true;  //光照信息
        configuration.getPointCloudData = false;   //点云

        //m_session.RunWithConfig(configuration);

        m_session.RunWithConfigAndOptions(configuration, UnityARSessionRunOption.ARSessionRunOptionRemoveExistingAnchors); //移除之前的平面

    }
}

捕获真实世界的信息

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.iOS;

public class HitResultController : MonoBehaviour {

	// Use this for initialization
	void Start () {
      

	}
	
	// Update is called once per frame
	void Update () {
        if (Input.touchCount > 0)
        {
            var touch = Input.GetTouch(0);
            if (touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Moved)
            {
                Vector3 screenPos = Camera.main.ScreenToViewportPoint(touch.position);  //将屏幕坐标转为视口坐标

                ARPoint point = new ARPoint
                {
                    x = screenPos.x,
                    y = screenPos.y
                };

                //ARHitTestResultType 枚举检测平面类型
                ARHitTestResultType[] resultTypes ={
                    ARHitTestResultType.ARHitTestResultTypeFeaturePoint, //与最近特征点相交的结果类型
                    ARHitTestResultType.ARHitTestResultTypeHorizontalPlane,
                    ARHitTestResultType.ARHitTestResultTypeExistingPlane, //与现有平面定位点相交的结果类型。
                    ARHitTestResultType.ARHitTestResultTypeExistingPlaneUsingExtent //考虑到平面的范围,与现有平面锚点相交的结果类型

                };
                //只要检测到枚举类型平面中的一种 就保存检测到的信息
                foreach (ARHitTestResultType resultType in resultTypes)
                {
                    List<ARHitTestResult> hitTestResults = UnityARSessionNativeInterface.GetARSessionNativeInterface().HitTest(point, resultType);  //获取一个点附近的检测信息 
                }

            }
        }
	}
}

hitTestResults 中就存在真实世界中的信息数据


放置物体到真实世界中

声明两个 GameObject     

 public GameObject Obj;

  private GameObject currentObj

要放置的物体拖到 Obj 在 foreach 中添加脚本

 //只要检测到枚举类型平面中的一种 就保存检测到的信息
                foreach (ARHitTestResultType resultType in resultTypes)
                {
                    List<ARHitTestResult> hitTestResults = UnityARSessionNativeInterface.GetARSessionNativeInterface().HitTest(point, resultType);  //获取一个点附近的检测信息 
                    if (currentObj==null)
                    {
                        currentObj = Instantiate(Obj);
                       
                    }
                    currentObj.transform.position = UnityARMatrixOps.GetPosition(hitTestResults[0].worldTransform); //获取position
                    currentObj.transform.rotation = UnityARMatrixOps.GetRotation(hitTestResults[0].worldTransform);
                }

自定义检测平面

创建材质球并附上贴图

创建plane预制体 拖到

插件内还提供几个


自定义点云

拖入创建的预制体 设置点云最大量和大小


阴影

插件中提供了预制体通过shadr 可显示阴影

在Directional Light 添加 UnityARAmbient 脚本可渲染真实世界光照


遮罩

是通过shader实现的 更换插件提供的平面预制体可实现


AR画画

创建预制体 添加LineRenderer组件 并创建脚本控制

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

public class LineController : MonoBehaviour {
    private LineRenderer lineRenderer;
    private List<Vector3> points=new List<Vector3>();
	// Use this for initialization
	void Start () {
        lineRenderer = this.GetComponent<LineRenderer>();
	}
    public void AddPoint(Vector3 pointt){
        Vector3 currentPos = pointt + (Camera.main.transform.forward * 0.2f);
        points.Add(currentPos);
        updateRanderer();
    }
    void updateRanderer(){
        lineRenderer.positionCount = points.Count;
        lineRenderer.SetPositions(points.ToArray());
    }
    public void SetColor(Color color){
        Material material = new Material(lineRenderer.material);
        material.SetColor("_Color", color);
        lineRenderer.material = material;
    }
}

相机添加插件中 UnityARCameraNearFar 脚本 可将相机的 near far 值复制给ar 相机

创建脚本FrameUpdateController 用来检测相机事件 把刚才创建的lineRenderer 赋值上去 

using UnityEngine;
using System.Collections;
using UnityEngine.XR.iOS;

public class FrameUpdateController : MonoBehaviour
{
    public GameObject linObj;
    private LineController lineController;
    private bool isDrawing; //是否开始绘画
    private Vector3 previousPos;  //上次位置

  
    private void OnEnable()
    {
        UnityARSessionNativeInterface.ARFrameUpdatedEvent += ARFrameUpdate;

    }
	private void OnDestroy()
	{
        UnityARSessionNativeInterface.ARFrameUpdatedEvent -= ARFrameUpdate;
	}

    /// <summary>
    /// 相机刷新时
    /// </summary>
    /// <param name="cam">Camera.</param>
    void ARFrameUpdate(UnityARCamera cam){
        
        Matrix4x4 matrix = new Matrix4x4();
        matrix.SetColumn(3, cam.worldTransform.column3); 
        Vector3 pos = UnityARMatrixOps.GetPosition(matrix); //通过矩阵类型转换 获取相机位置
        print(pos);
        if (isDrawing&&Vector3.Distance(pos,previousPos)>0.01f)
        {
            lineController.AddPoint(pos);
            previousPos = pos;
        }
       

    }

	private void OnGUI()
	{
        if (GUI.Button(new Rect(100,200,200,100),"Start"))
        {
            isDrawing = true;
            lineController = Instantiate(linObj, this.transform).GetComponent<LineController>();
        }
        if (GUI.Button(new Rect(100, 400, 200, 100), "Pause"))
        {
            isDrawing = false;
        }
        if (GUI.Button(new Rect(100, 600, 200, 100), "ChangeColor"))
        {
            Color color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
            lineController.SetColor(color);
        }
	}

}

可通过GUI Button 点击开始进行绘画


插件核心代码

 

常用方法

委托事件

锚点信息

获取相机位置


案例分析

UnityARKitScene 点击放置物体

UnityParticlePainter  空间例子系统画点  (空间作画)

UnityARBallz 平面小球移动与碰撞(模拟小球平掉落到另外平面)

UnityARShadows 在平面显示物体阴影

UnityAROcclusion 遮光材料遮挡物体

FocusSquareScene  视点聚焦 (检测时给其动态效果)

AddRemoveAnchorScene 通过Anchor添加删除物体

猜你喜欢

转载自blog.csdn.net/qq_39741605/article/details/89205121
今日推荐