【Unity】PolySpatial 1.0 →2.0 のアップデート情報まとめ【VisionOS】

Graffity でUnityエンジニアをしている cova です。

今回は来たるVisionOS の次期バージョン visionOS2.0 に対応する
Unity 用SDK `PolySpatial2.0` が 1.x系から何が良くなってるのかの日本語情報をまとめました。

# 検証環境

| 項目 | Version |
|--- |--- |
|Unity| Unity6000.0.12f1 |
|PolySpatial| 2.0-pre11 |
| visionOS | VisionOS2.0-beta6 /  VisionOS2.0-beta7 |
| Xcode | 16.0 beta 6 |

# せっかちな方へ
Visual 込みで確認したい場合はUnityの限定公開で公開しているPolySpatial の動画をご覧ください

<iframe width="560" height="315" src="https://www.youtube.com/embed/x20Syu6EP5o?si=Iao7PTOV2kjbHHPk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

# Update内容
現状との差分をわかりやすくするために5つのカテゴリに分けて説明します

1. visionOS1.0 で機能はあったけど PolySpatial 1.0 で非対応→2.0からできるようになること
1. PolySpatial2.0 で 対応している機能
1. PolySpatial2.0 で 対応予定の機能
1. 執筆時点で visionOS1.0 にはあるがPolySpatial2.0 では対応されない機能
1. 執筆時点で visionOS2.0 にはあるがPolySpatial2.0 では対応されない機能

## visionOS1.0 で機能はあったけど PolySpatial 1.0 で非対応→2.0からできるようになること
- MultiVolume のサポート
- PlayToDevice のAR/MR系コンテンツ対応

### MultiVolumeのサポート
- SharedSpace での複数表示
    - ![IMG_0119.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/17622bbb-f0b6-a7b7-1557-4d18cc099aea.png)
- Immersive Space でのVolume表示
    - AR/MR 空間上でもVolumeを生成できます

共通して言えるのは
- Prefab でもSceneのAdditive でもVolumeコンテンツは追加可能
- VolumeCameraと描画用のCameraがあれば良いみたい
- Gaze&Tapで操作できるのは `Defaultレイヤーのオブジェクトのみ`
- Volume を複数生成するときは描画対象をうまく切り分けないとVolumeAにVolumeBの内容が重なって表示されたりする

### PlayToDevice のAR/MR系コンテンツ対応
AR/MR開発者待望の機能です!!
    

ついに現実空間でスキャンしたMesh情報とかがHierarchyにどんな感じで生成されるのかを
リアルタイムにEditor を見つつ確認できるようになりました。

また今まではImmersive Space アプリはビルドしないと実機確認できませんでしたが
これからはPlayToDevice2.0系を利用することでビルドなしで大部分は確認できるようになるので開発イテレーションがだいぶ早くなると思います。

## PolySpatial 2.0 で 対応している機能
- DynamicLighting 
- Resizeable Volume
- Custom Hover Effect
- BlendShape
- BillboardComponent
- Particle のBakeToTexture
- Stereo Render Target

### Dynamic Lighting
Light Component によるライティングができるようになりました。

https://docs.unity3d.com/Packages/com.unity.polyspatial.visionos@2.0/manual/PolySpatialLighting.html

今まではBakeしてないと使えなかったのが動的にライトを動かしても反映できるようになります。

![LightSettings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/0c901ccb-22fc-0774-b626-1d920b96625b.png)

LightComponentとVisionOSLightSettings Componentをアタッチすることで指定のライトが使えます

### Resizeable Volume

今までVolumeなアプリはコーナーに視線を持っていくとスケールを変更するUIが表示。
それを選択することでスケールをいじれました。

今回からは VolumeCamera.ScaleWithWindow フラグを設定することでScaleの代わりに
描画範囲の拡大縮小ができるようになります

https://docs.unity3d.com/Packages/com.unity.polyspatial@2.0/api/Unity.PolySpatial.VolumeCamera.html#Unity_PolySpatial_VolumeCamera_ScaleWithWindow

![resize.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/ed372328-9c56-9564-6db3-11e3af324512.gif)

### Custom Hover Effect
![hover_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/b0a6085e-e550-219d-5394-7ebfabf1c3a9.png)

このような形で従来はHover時には白くなるだけだったのがある程度色をユーザーで設定できるようになりました。

![hover.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/e39759ba-2cb1-7399-b342-914bbeb80fca.png)

https://docs.unity3d.com/Packages/com.unity.polyspatial@2.0/api/Unity.PolySpatial.VisionOSHoverEffect.EffectType.html

基本的には従来の VisionOSHoverEffect が改良された形で、ユーザー的にパッと思う「HoverEventがCustomできるようになった！？」ではありません。

あくまでも CustomHover `Effect` であり CustomHover `Event` ではないんですよね。

（個人的には OnHoverBegin, OnHoverEnd 的なイベントだけでもとれるようにしてほしいですが。。。）


### BlendShape

とくに3Dアバター系コンテンツ開発者には朗報だと思います。
（PolySpatialの開発者からも要望はかなり多く上がっており公式のLoadmapでもVote数は多かった機能です）
![blendshape.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/1187e748-df12-144c-e91e-f1aa2f0a2233.gif)

シンプルにBlendShape 対応なので一番わかりやすいのは表情変化ですが、Apple 公式のSampleでは植物の成長だったり元気度合いを表現してたりします。

https://developer.apple.com/jp/videos/play/wwdc2024/10102/?time=1643

![BS_AnimDef.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/df60beac-fde6-21ee-1532-0c00bc8f38ed.png)

![plant.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/164e5506-7d7f-3ac6-cfc1-54dea0ae5757.gif)

### BillboardComponent

Billboard とはUI等が常にカメラの正面になるように回転を自動で設定する演出です

https://docs.unity3d.com/Packages/com.unity.polyspatial@2.0/api/Unity.PolySpatial.VisionOSBillboard.html

Unityではよくある方法としては Camera.main.transform.rotation の値をUIとかにそのままor前後逆で適応することで、カメラを動かしてもUIが常に正面から見えるようにしたり、背景画像を常に見せる、あとはParticleを表示するときも板ポリゴンとわからないようにBillboardOptionがあったりします。

今回はVisionOSのBillboard 機能のproxyとして VisionOSBillboard コンポーネントが提供されており、開発者側からRotationをいじるみたいな実装はできないようです。

### Particle のBakeToTexture
![particle.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/4a55dc17-c1fc-2699-5db6-d9ab1e8aceb2.gif)

待望of待望な機能だと思います。
1.0系でもParticleは使えましたが `BakeToMesh` じゃないと正しく表示されませんでした。

また、BakeToMeshにしているせいなのか、半透明を使ったParticleの場合に時折綺麗に表示されないなどの不具合もありました。
また、MeshにBakeすることから、板ポリゴンでなくMeshParticle での実装になるため負荷も重めなことが多かったのも事実です。

今回からはBakeToTexture が使えるようになったことで板ポリゴンをわざわざ用意せず、かつアーティストの意図通りに表示できるようになりました。

### Stereo Render Target

TBD

## PolySpatial2.0 で 対応予定の機能
- Mode Switching
- Metal を使った描画

:::note warn
Metal 周りの機能は本来は１個上の対応している機能に入る予定でしたが
記事執筆時点ではUI操作ができないなど、開発にクリティカルな問題が発生しているためこちらのカテゴリに入れました

こちらに関しては動かすための設定方法含めて要追加調査という状態です

https://issuetracker.unity3d.com/issues/visionos-ui-in-the-metal-sample-for-apple-vision-pro-does-not-work
:::




## 執筆時点で visionOS1.0 にはあるがPolySpatial2.0 では対応されない機能
- Spatial Audio 全般
- Persona

### Spatial Audio
これは筆者の予測ですが、PolySpatial側というよりは、Unityが利用しているサウンドエンジンである `FMOD` 側がVisionPro 向けに機能を提供できていないことに起因すると思われます。
そのため単純に visionOS向けにコンバートするだけじゃなく、FMOD側にも修正リクエストを投げる形になるため難航していると思います。

（サウンドってちょっと変更しただけでバリバリバリみたいな爆音ノイズになりやすいから修正って大変ねんな）

### Persona
自分の上半身アバターを相手に表示したり、相手の上半身アバターを自分の環境に表示したりするあれです

ただ、こちらに関してはすんごく頑張ってSwift Pluginを作れば動かすことも可能らしいので
どうしても公式対応が我慢できない場合は自作する道に進むしかないです


## 執筆時点で visionOS2.0 にはあるがPolySpatial2.0 では対応されない機能
- HandTracking の90Hz対応
    - VisionOS1.x系だと30Hzでしかトラックしてない
- Shader Graph系
    - ブラー
    - DepthMap のRead/Write
    - Back Culling
- surroundingseffect
- SharePlay 

###  HandTracking の90Hz対応

MR開発者なら喉から手が出るほど欲しい機能ですが現時点では未対応だそうです。

これが導入されれば手のMesh追随とかの速度があがってラグくなくなると思われるのでUX的にも早く欲しいですね

### ShaderGraph 系
こちらは Apple のRealityKit 側の問題とmaterialの規格であるMaterialX 側の問題の2種類があるため、対応コストは少し高い状態です。
前者に関してはUnity側が頑張ればいけますが、MaterialXについては規格が対応してくれないと実機で再現不能だったりします（UnityのMaterialPropertyBlockが使えないとかね）

こちらも気長に待つしかないですね

### surroundingseffect
https://developer.apple.com/jp/videos/play/wwdc2024/10153/?time=1743

![passthroughcolor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65257/0f7639ed-de1b-e346-6fb7-95a9f35fcea5.png)

パススルー映像に色を乗算できる機能ですが、提供されているAPIが ImmersiveSpaceなViewに対してColor設定イベントを設定するというものになります。

```
// Apply effect to tint passthrough
struct ImmersiveExplorationView: View {
    var body: some View {
        RealityView { content in
            // ...
        }
        .preferredSurroundingsEffect(surroundingsEffect)
    }

    // The resolved surroundings effect based on tint color
    var surroundingsEffect: SurroundingsEffect? {
        if let color = appModel.tintColor {
            return SurroundingsEffect.colorMultiply(color)
        } else {
            return nil
        }
    }
}
```

Unity ではViewはUnity側が管理しており、現在のViewに対する操作はRuntimeではできません。
また、VisionOSのビルド時にUnityが管理しているViewのコードが生成されるため、現状では

1. Unity 側でビルド
1. 生成されたSwift Codeに手を加える
1. Xcodeでビルド

といった形でNativePluginでも対応できず、ビルド後のSwiftコードに手を入れるしかないです。
そのためUnity側からRuntimeで色を操作することも難しく（もしかしたら色の定義を外だししてそれをNativePluguin経由で書き換え & View側はその値を参照するようにしたらできるかもしれないですが）、現状はアップデート待ちという形になります。

### SharePlay
Persona と状況は近いと思います。
一応Photon 等のマルチプレイ用のミドルウェアを用いて、ユーザーの表示位置を予め固定して同期させれば、それっぽいことはできます。

しかし結局のところPersona を表示することが肝になっている機能ではあるので場所の自動同期システムを作っても価値は半分以下といったところでしょう。

こちらもPersona待ちといった状態です

# まとめ
今回はPolySpatial1.0→2.0のアップデート周りの情報を日本語化&実際の状況について解説しました。

まだPolySpatial2.0 もpreview版であるため随時情報は更新していきたいと思います。