当前位置: 首页 > article >正文

PICO+Unity MR空间锚点

官方链接:空间锚点 | PICO 开发者平台

注意:该功能只能打包成APK在PICO 4 Ultra上真机运行,无法通过串流或PICO developer center在PC上运行。使用之前要开启视频透视。

Inspector 窗口中的 PXR_Manager (Script) 面板上,勾选 Spatial Anchor 选框,为应用开启空间锚点能力。然后,你可以调用空间锚点相关接口,在应用内实现空间锚点功能。

新建一个空物体名为SpatialAnchor,添加SpatialAnchor组件(指定地方放置物体)、SeethroughManager代码(开启透视)

编写代码SpatialAnchor

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class SpatialAnchor : MonoBehaviour
{
    public GameObject prerefAnchor;
    public GameObject anchorPreview;
    public GameObject firePoint;

    public Text textPrompt;
    public Button btnLoadAllAnchors;
    public Button btnClearAllAnchors;
    [SerializeField]
    private InputActionReference rightGrip;

    public Dictionary<ulong, AnchorInfo> anchorList = new Dictionary<ulong, AnchorInfo>();
    // Start is called before the first frame update
    void Start()
    {
        btnLoadAllAnchors.onClick.AddListener(OnBtnPressedLoadAllAnchors);
        btnClearAllAnchors.onClick.AddListener(OnBtnPressedClearAllAnchors);
        StartSpatialAnchorProvider();
    }

    private void OnEnable()
    {
        rightGrip.action.started += OnRightGripPressed;
        rightGrip.action.canceled += OnRightGripReleased;
    }

    private void OnDisable()
    {
        rightGrip.action.started -= OnRightGripPressed;
        rightGrip.action.canceled -= OnRightGripReleased;
    }

    //called on action.started
    private void OnRightGripPressed(InputAction.CallbackContext callback)
    {
        ShowAnchorPreview();
    }

    //called on action.release
    private void OnRightGripReleased(InputAction.CallbackContext callback)
    {
        CreateAnchor();
    }

    private void ShowAnchorPreview()
    {
        //Show anchor
        anchorPreview.SetActive(true);
    }

    private async void StartSpatialAnchorProvider()
    {
        var result0 = await PXR_MixedReality.StartSenseDataProvider(PxrSenseDataProviderType.SpatialAnchor);
        Debug.unityLogger.Log($"StartSenseDataProvider: {result0}");
    }    

    private async void CreateAnchor()
    {
        anchorPreview.SetActive(false);
        //Use Spatial Anchor Api to create anchor
        //This will  trigger AnchorEntityCreatedEvent
        var result1 = await PXR_MixedReality.CreateSpatialAnchorAsync(firePoint.transform.position, firePoint.transform.rotation);
        if (result1.result == PxrResult.SUCCESS)
        {
            GameObject anchorObject = Instantiate(prerefAnchor);
            anchorObject.SetActive(true);
            anchorObject.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            anchorObject.transform.rotation = firePoint.transform.rotation;
            anchorObject.transform.position = firePoint.transform.position;

            AnchorInfo info = anchorObject.GetComponent<AnchorInfo>();

            var result2 = await PXR_MixedReality.PersistSpatialAnchorAsync(result1.anchorHandle);
            if (result2 == PxrResult.SUCCESS)
            {
                info.ShowSaveIcon(true);
            }
            else
            {
                info.ShowSaveIcon(false);
            }
            anchorList.Add(result1.anchorHandle, info); // 添加到锚点列表
        }
    }

    // 异步加载所有锚点
    private async void OnBtnPressedLoadAllAnchors()
    {
        anchorList.Clear();
        var result = await PXR_MixedReality.QuerySpatialAnchorAsync(); // 查询所有空间锚点
        //SetLogInfo("LoadSpatialAnchorAsync:" + result.result.ToString() + result.anchorHandleList.Count); // 记录日志
        if (result.result == PxrResult.SUCCESS) // 成功查询
        {
            int i = 0;
            foreach (var key in result.anchorHandleList) // 遍历锚点句柄
            {
                if (!anchorList.ContainsKey(key)) // 如果锚点列表中不存在该锚点
                {
                    i++;
                    PXR_MixedReality.LocateAnchor(key, out var position, out var orientation);
                    GameObject anchorObject = Instantiate(prerefAnchor);
                    anchorObject.SetActive(true);
                    anchorObject.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
                    anchorObject.transform.rotation = orientation;
                    anchorObject.transform.position = position;
                    AnchorInfo anchor = anchorObject.GetComponent<AnchorInfo>(); // 获取锚点组件
                    anchor.SetAnchorHandle(key); // 设置锚点句柄
                    // 定位锚点
                    anchorList.Add(key, anchor); // 添加到锚点列表
                    anchorList[key].ShowSaveIcon(true); // 显示保存图标
                }
                else
                {
                    textPrompt.text = "无法加载:" + i.ToString();
                }
            }
        }
        else
        {
            textPrompt.text = "查询失败...";
        }
    }

    // 异步删除所有锚点
    private async void OnBtnPressedClearAllAnchors()
    {
        List<ulong> keys = anchorList.Keys.ToList();
        for(int i = 0; i < keys.Count; i++)
        {
            ulong key = keys[i];
            await PXR_MixedReality.UnPersistSpatialAnchorAsync(anchorList[key].anchorHandle);

            textPrompt.text = "正在删除..."+i.ToString();
            DestroyImmediate(anchorList[key].gameObject);
        }

        anchorList.Clear();
        textPrompt.text = "删除完成";
    }
}

锚点信息类 

using System.Collections;
using System.Collections.Generic;
using Unity.XR.PXR;
using UnityEngine;
using UnityEngine.UI;

public class AnchorInfo : MonoBehaviour
{
    public Text text;
    public GameObject savedIcon;

    [HideInInspector]
    public ulong anchorHandle;
    // 设置锚点句柄并更新 UI 显示
    public void SetAnchorHandle(ulong handle)
    {
        anchorHandle = handle;
        text.text = "ID: " + anchorHandle;
    }

    // 显示保存图标
    public void ShowSaveIcon(bool show)
    {
        savedIcon.SetActive(show);
    }

    private void LateUpdate()
    {
        // 尝试定位空间锚点
        var result = PXR_MixedReality.LocateAnchor(anchorHandle, out var position, out var rotation);
        if (result == PxrResult.SUCCESS)
        {
            // 如果成功,更新当前对象的位置和旋转
            transform.position = position;
            transform.rotation = rotation;
        }
    }
}

rightGrip输入赋值 


http://www.kler.cn/a/391390.html

相关文章:

  • [Xshell] Xshell的下载安装使用、连接linux、 上传文件到linux系统-详解(附下载链接)
  • 法学硕士,有哪些专业可以申请呢?
  • 腾讯云智能结构化OCR:以多模态大模型技术为核心,推动跨行业高效精准的文档处理与数据提取新时代
  • vue iframe进行父子页面通信并切换URL
  • javaEE-线程的常用方法-4
  • 3. Kafka入门—安装与基本命令
  • python设计模式
  • 中国地区数据要素化水平数据集(2010-2023年)
  • 安全升级,从漏洞扫描开始:专业级网络安全服务
  • flutter调试
  • D3入门:学习思维导图 + 99个中文API详解
  • 【C++】 C++游戏设计---五子棋小游戏
  • Qt生成coredump文件(支持arm和x86架构)
  • opencv保姆级讲解——光学学符识别(OCR)(4)
  • Docker部署Nginx服务器并实现HTTPS自动重定向
  • 【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-成绩排序
  • 【ECMAScript标准规范】
  • 「QT」基础数据类 之 QVariant 通用数据类
  • PHY6235超低功耗蓝牙和专有2.4G应用的SOC芯片内置MCU
  • Git 中的 patch 功能
  • 生成式模型的热点新闻和进展
  • 第8章利用CSS制作导航菜单
  • 鸿蒙ZRouter动态路由框架—生命周期管理能力
  • 论云游戏的性能与性价比,ToDesk、青椒云、顺网云游戏等具体实操看这篇就够了
  • SAP ABAP开发学习——function alv复选框设置
  • [论文阅读]Enhanced Membership Inference Attacks against Machine Learning Models