😽

visionOS Reality Composer Pro の試してみた

2023/07/31に公開

visionOS で 3Dコンテンツを作成するときには Reality Composer Pro を使用して作成するのですが、実際にどうやって作成しているのか、実際に試してみました。

RealityComposerProとは

VisionPro で 3D空間に3Dモデルを配置するには RealityComposerProを使用して簡単に配置をすることができます。
UnityやUnrealEngineのようなゲームエンジンのように3D空間上にオブジェクト(Entity)を配置し、オブジェクトに対してコンポーネントをつけることで、機能を付与することができます。
SwiftUI上ではこのRealityComposerProで作成したシーンを読み込むことで3D空間上にオブジェクトを配置することができます。
https://developer.apple.com/videos/play/wwdc2023/10083

環境構築

visionOSの開発を行うには Xcodeのベータバージョンをダウンロードして使用する必要があります。
https://developer.apple.com/download/all/?q=xcode 15
ここから Xcode 15 の bataバージョンをダウンロードしてインストールします。
現在は beta5 があるのでそちらをインストールしています。
image

ダウンロードしたxidを展開して出てきたXcodeを開きvisionOSにチェックをinstallを行ってください。
image

ダウンロードしたXcodeを開きCreateProjectからvisionOS向けのプロジェクトを作成します。
image

次にプロジェクトの設定を行います。
空間上にオブジェクトを表示するので Initial Scene は Volume にします。
Immersive Space は バーチャル空間をどのように使用するかなのですが、今回はMixにして現実空間と一緒に表示されるようにします。
image

作成されたプロジェクトを開くとコードとプレビューの表示が一緒に表示されます。
プレビューの表示は選択しているファイルのViewが表示されている状態です。
試しに、ContentViewからImmersiveViewのファイルを選択すると表示が切り替わるのが確認できると思います。
再生し Enlarge RealityView Contentボタンを押すと 球体の大きさが変わり、Show Immersive Space ボタンを押すと空中に2つ球体が表示されるのが確認できます。
image

RealityComposerPro

表示されている球体は Reality Compooser Pro で設定され表示されています。
ContentView では Reality Composer Pro で作成した realityKitContentBundle にある Scene という名前のシーンを読み込んでいます。

RealityView { content in
    // Add the initial RealityKit content
    if let scene = try? await Entity(named: "Scene", in: realityKitContentBundle) {
        content.add(scene)
    }
}

続いてImmersiveViewを見てみましょう。ImmersiveViewではImmersiveという名前のシーンを読み込んでいます。

RealityView { content in
    // Add the initial RealityKit content
    if let scene = try? await Entity(named: "Immersive", in: realityKitContentBundle) {
        content.add(scene)
    }
}

ではこの中身をReality Composer Proで確認してみましょう。
Packages/RealityKitContent/Packageを選択してOpen in Reality Composer Proを選択して Reality Composer Proを開きます。

image

Reality Composer Proを開くと球体が表示しているシーンが開きます。
このシーン上にEntityを配置することで空間にオブジェクトを設置していきます。
今は Immersiveのシーンが開いている状態なので球体が2つシーン上に配置されています。
image

Scene シーンをダブルクリックして開くと ContentView で表示している球体が1つのシーンが表示されます。
image

試しに Sceneにオブジェクトを追加してみましょう。
左下の+マークから Primitive Shape/Cube を選択して 立方体を追加します。
Root以下に移動させ、球体の上に配置してみましょう。
image
image

セーブしてXcodeに戻り、ContentViewを選択すると立方体が追加されているのが確認できると思います。
Reality Composer Proで編集した内容をセーブすると自動的に Xcode 上でも反映されて確認することができます。
image

Component

次は SceneにあるSphereを選択してコンポーネントを確認してみましょう。
image

TransformはかならずEntityにつくコンポーネントで位置、回転、大きさを表しています。
MaterialBindingは使用するマテリアルを設定し、SpherePrimitiveは球体モデルのメッシュを表現しています。
Collisionは当たり判定を設定していおり、InputTargetをつけることでヒットしたユーザーの入力イベントを検知できるようになります。

入力イベントは ContentView の Gesture部分で設定しています。
ContentViewではオブジェクトをクリックしても大きさが変わるようになっています。

.gesture(TapGesture().targetedToAnyEntity().onEnded { _ in
    enlarge.toggle()
})

EntityCompoonentSystem

visionOSのコンポーネントはEntityComponentSystemという仕組みで動作しています。
image

コンポーネントでEntityに情報を追加し、
システムの方でコンポーネントを元にどう動作するかを実装します。

それではコンポーネントとシステム作成してみましょう。
今回は並行移動させる機能を作っていきたいと思います。

Cubeを選択して 右下の AddComponentを選択し、New Componentを選択します。
image

コンポーネントの名前を入力してコンポーネントを作成します。
image

これで作成したコンポーネントがCubeにつきました。
Xcodeに戻り 作成したMoveComponentを編集していきましょう。
MoveComponentPackages/RealityKitContent/Sources/RealityKitContent/MoveComponentに作成されています。
image

今回は移動をさせるために velocityをコンポーネントに追加しましょう。
SIMD は ベクトルを表現するための型で 今回は3次元ベクトルの SIMD3<Float> を使用しています。

import RealityKit

// Ensure you register this component in your app’s delegate using:
// MoveComponent.registerComponent()
public struct MoveComponent: Component, Codable {
    var velocity : SIMD3<Float> = [0.0,0.0,0.0]

    public init() {
    }
}

RealityComposerProに戻ってMoveComponent を確認してみると Velocityが追加されています。
奥に動くようにzに -0.01 を入れておきましょう.
image

次にこれを動作させるためにMoveComponentと同じ階層にシステムを作成します。
Xcodeに戻りRealityKitContentを選択してNewFileを選択し、名前をMoveSystemとします。
image

ファイルを作成したらMoveSystemの中身を実装しましょう。

import RealityKit

public struct MoveSystem: System {
    
    static let query = EntityQuery(where: .has(RealityKitContent.MoveComponent.self))

    public init(scene: Scene) {
    }
    
    public func update(context: SceneUpdateContext) {

        let entities = context.scene.performQuery(Self.query).map({ $0 })

        if entities.isEmpty {
            return
        }
        
        for entity in entities {
            let moveComponent = entity.components[RealityKitContent.MoveComponent.self]!;
            entity.transform.translation += moveComponent.velocity;
        }
    }
}

上から見ていくと query ではシーンからどのコンポーネントを取得するかのクエリを定義しています。
今回は MoveComoponentを取得して操作するためMoveComopnentを取得するクエリを定義します。

static let query = EntityQuery(where: .has(RealityKitContent.MoveComponent.self))

シーンに対してクエリを指定して対象のEntityを取得してきます。

let entities = context.scene.performQuery(Self.query).map({ $0 })

取得したEntityからMoveComponentを取得してtransform.translationvelocityを足してあげます。
updateでは毎フレーム処理が呼ばれるためvelocity方向に位置が移動し続けます。

for entity in entities {
    let moveComponent = entity.components[RealityKitContent.MoveComponent.self]!;
    entity.transform.translation += moveComponent.velocity;
}

これでMoveSystemの実装は完了です。
次に作成したコンポーネントとシステムを使用できるように登録しましょう。
まずは RealityComposerProTestAppinitを追加します。
コンポーネントはregisterCompoonent, システムはregisterSystemで登録を行います。

import RealityKitContent
struct RealityComposerProTestApp: App {
    init(){
        RealityKitContent.MoveComponent.registerComponent()
        RealityKitContent.MoveSystem.registerSystem()
    }
    var body: some Scene {
        ....
    }
}

これでシステムとコンポーネントが動作するようになりました!
それでは動作を確認してみましょう。
image

立方体が奥へ進んでいくようになりました!
コンポーネントにしているため他のオブジェクトにコンポーネントをつけることで同じように動作させることができます。
球にもコンポーネントをつけてみましょう。
今度は手前に移動させるように z に 0.01 を入れます。
image

ContentViewに戻って確認すると立方体と球が動いているのが確認できます。
image

まとめ

RealityComposerProを使用するとGUI上でシーンにオブジェクトを配置することができます。
また、ComponentとSystemを使用することでComponent単位で挙動を実装することが可能です。
これはUnityやUnrealなどのゲームエンジンに近い形でシーンを構築できるため便利でした。
今回は紹介しませんでしたが音の発生源を追加したり、ShaderGraphによってシェーダの作成も可能です。
RealityComposerPro使いこなしていきましょう!
(Unityでできるのであればそちらの方が良さそうですが・・)

書いた人

ひー

佐藤 寿樹

株式会社コナミデジタルエンタテインメントに入社し5年間ウイニングイレブンのオンライン実装に携わる。
その後、株式会社コロプラで9年間エンジニアとしてアプリ開発・運用を行い、位置情報やARを使用したARゲーム開発、OculusRiftやPSVRなどのVRゲーム開発を経験しMESONへ入社。

Twitter

MESON Works

MESONの制作実績一覧もあります。ご興味ある方はぜひ見てみてください。

MESON Works

Discussion