土鍋で雑多煮

UnityでXR・ゲーム開発をしています。学んだことや備忘録、趣味の記録などを書いていきます。

MENU

【Unity】MRUK (Meta XR SDK)の最新アプデをやってみる【MRUK v71】

はじめに

どうも、土鍋です。

先日、Meta XR SDKのMR機能パッケージであるMRUK(Mixed Reality Utility Kit)にアップデートが来ました。 面白そうな機能がいくつか追加されていたのでやってみました。

↓リリースノート

developers.meta.com

Environment Raycast Manager

部屋に対するRaycastを行えるようにします。

空のオブジェクトを作成し、Environment Raycast Managerを追加します。

これを使うためのコードを書いていきます。

using Meta.XR;
using UnityEngine;

public class SceneRaycastTest : MonoBehaviour
{
    [SerializeField] 
    private EnvironmentRaycastManager _raycastManager;

    [SerializeField] 
    private Transform originTransform;

    [SerializeField] private GameObject pointer;

    private Ray _ray;
    
    private void Start()
    {
        _ray = new Ray(originTransform.position, originTransform.forward);
    }

    private void Update()
    {
        _ray.origin = originTransform.position;
        _ray.direction = originTransform.forward;

        if (_raycastManager.Raycast(_ray, out var hit))
        {
            if (hit.status == EnvironmentRaycastHitStatus.Hit)
            {
                //Debug.Log($"hit: {hit.point}, {hit.normal}");
                pointer.transform.position = hit.point;
                pointer.transform.rotation = Quaternion.LookRotation(hit.normal);
            }
        }
    }
}

使い方は大体、通常のRaycastと同じです。

今回は手からRayを飛ばしてます。

Raycastして部屋のメッシュにRayが当たると EnvironmentRaycastHit が取得できるので、これからヒット位置の3次元座標とヒット平面との法線ベクトルなどが取得できます。

EnvironmentRaycastHitStatus でRaycastステータス情報が取得できます。

公式ドキュメントはこちら

developers.meta.com

Destructible Global Mesh

破壊可能な部屋のメッシュデータを扱えるようになりました。

空のオブジェクトにDestructible Global Mesh Spawnerを追加します。
Global Mesh Materialにマテリアルを指定することでGlobal Meshを可視化できます。

※ Meta XR Simulatorを使用することでビルドせずに部屋のメッシュのテストができます。

donabenabe.hatenablog.com

再生するとGlobalMeshの子オブジェクトにDestructible Global Mesh Segmentが生成されているのが確認できます。

これがGlobal Meshが分割されたメッシュです。これを消すことで、現実の壁を破壊したかのような表現が作れます。

先程のEnvironment Raycastと組み合わせて、指さした壁を破壊する表現を作ってみます。

↓分割されたメッシュを取得して、MeshColliderを追加しています。

using Meta.XR.MRUtilityKit;
using UnityEngine;

public class DestructibleGlobalMeshTest : MonoBehaviour
{
    [SerializeField] 
    private MRUK mruk;
    [SerializeField]
    private DestructibleGlobalMeshSpawner _globalMeshSpawner;

    private void Start()
    {
        _globalMeshSpawner.OnDestructibleMeshCreated.AddListener(_ =>
        {
            Debug.Log("mesh created");
            MRUKRoom room = mruk.GetCurrentRoom();
            if (_globalMeshSpawner.TryGetDestructibleMeshForRoom(room,out var globalMesh))
            {
                Debug.Log($"mesh: {globalMesh.DestructibleMeshComponent.GetDestructibleMeshSegmentsCount()}");
                
                foreach (var mesh in globalMesh.DestructibleMeshComponent.transform.GetComponentsInChildren<Transform>())
                {
                    if(mesh == globalMesh.DestructibleMeshComponent.transform)continue;
                    mesh.gameObject.AddComponent<MeshCollider>();
                }
            }
        });
    }
}

DestructibleMesh生成時に発火する OnDestructibleMeshCreated のUnityEventを購読して実行しています。

TryGetDestructibleMeshForRoomで DestructibleGlobalMesh を取得し、さらに生成される分割メッシュDestructibleMeshの親オブジェクトであるDestructibleMeshComponentを取得します。

↓ ポインターオブジェクトにアタッチするスクリプト
指をピンチすると破壊する。

public class DestroyRoomMesh : MonoBehaviour
{
    [SerializeField] private OVRHand _hand;

    private GameObject selectObject;
    
    private void Update()
    {
        if (_hand.GetFingerIsPinching(OVRHand.HandFinger.Index))
        {
            if (selectObject==null) return;
            
            Debug.Log("Destroy");
            selectObject.SetActive(false);
        }
    }
    
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("select: " + other.gameObject);
        selectObject = other.gameObject;
    }
}

破壊された先にバーチャル空間を出す方法は以下をご覧ください。

donabenabe.hatenablog.com

ということで完成しました。

公式ドキュメントはこちら

developers.meta.com

参考

www.patreon.com