RealityKitをnonARモードで使ってみた
Xcode 16からiOSでもReality Composer Proが利用できるようになったので、こちらで紹介しています
コードでそれぞれ設定しても良いのですが、Reality Composer Proでシーンを作成する方が便利です
RealityKitはAR表示を推しているFrameworkですが、CameraModeに.nonARがあったので、これを試してみました
作成したみたものがコチラ↓です
RealityKitをnonARモードで使ってみたhttps://t.co/Ms9okoRYls pic.twitter.com/51X0BxqU59
— ふじき (@fzkqi) July 23, 2024
Xcode 15からReality Composerが利用できなくなったため、加筆修正しました
arモードとnonARモードで違う所
基本的にRealityKitはarモードでもnonARモードでも同じように扱うことができました
nonARモードで意識したのは下記の4点です、順番に取り扱って行きます
- ARViewをnonARで作成する
- カメラの追加
- Lightの追加
- Skyboxの設定
- これらを1つのAnchorに追加する
ARViewをnonARで作成する
cameraModeをnonARでARViewを作成します
let arView = ARView(frame: .zero, cameraMode: .nonAR, automaticallyConfigureSession: false)
USDZの読み込み
USDZファイルを読み込んでモデルを表示します
アニメーションがあれば、リピートで再生させます
Appleのサイトからダウンロードしてきました
let plane = try ModelEntity.loadModel(named: "toy_biplane_idle")
plane.availableAnimations.forEach {
plane.playAnimation($0.repeat())
}
let worldAnchor = AnchorEntity(world: .zero)
worldAnchor.addChild(plane)
arView.scene.anchors.append(worldAnchor)
こちらが結果です
飛行機が表示されているようですが、イマイチわかりません🥺

カメラの追加
arモードではカメラの位置はデバイスの位置になるのですが、nonARモードでは手動でカメラを追加してあげる必要があります
PerspectiveCameraを使用します
適当にカメラの位置と向きを設定します
let camera = PerspectiveCamera()
camera.camera.fieldOfViewInDegrees = 60
camera.look(at: .zero, from: [1, 0.5, 1], relativeTo: nil)
worldAnchor.addChild(camera)
こちらが結果です
斜め上から見ているので分かりやすくはなりましたが、真っ暗でよくわかりません🥺

Lightの追加
真っ暗なので、Lightを追加します
LightはPerspectiveCamera、DirectionalLight、SpotLightの3種類があります
今回はDirectionalLightを配置しました
let directionalLight = DirectionalLight()
directionalLight.light.color = .white
directionalLight.light.intensity = 5000
directionalLight.look(at: .zero, from: .init(x: 0, y: 20, z: 5), relativeTo: nil)
worldAnchor.addChild(directionalLight)
こちらが結果です
飛行機は明るくなりましたが、背景が真っ暗で寂しいです🥺

Skyboxの設定
ARView.Environment.Background.skyboxを使って背景として設定します
- https://polyhaven.com/a/alps_fieldから全天球の画像をダウンロードします
-
{任意の名前}.skybox
というリファレンスフォルダを追加し、その中にダウンロードした画像を配置します
-
EnvironmentResource.load(named: "{任意の名前}")
でロードして、backgroundに設定します
*{任意の名前}.skybox
というリファレンスフォルダがある場合、ビルド時に自動的にrealityenvファイルに変換され、アプリにバンドルされるようです
let skybox = try! EnvironmentResource.load(named: "alps_field_1k")
arView.environment.background = .skybox(skybox)
Swift Packageでは.skyboxを処理してくれなかったため、Swift Packageのみで設定する場合、オレオレSkyboxを作成して追加します
let skyboxTexture = try TextureResource.load(named: "alps_field_1k", in: .module)
var skyboxMaterial = UnlitMaterial()
skyboxMaterial.color = .init(texture: .init(skyboxTexture))
let skyboxComponent = ModelComponent(mesh: .generateSphere(radius: 1000), materials: [skyboxMaterial])
let skybox = Entity()
skybox.components.set(skyboxComponent)
skybox.scale *= .init(1, 1, -1)
worldAnchor.addChild(skybox)
こちらが結果です
全体的に明るくなってイイ感じです!

これらを1つのAnchorに追加する
これはワンポイントで、上でしれっとやっているのですが、カメラなど表示に必要なものを1つのAnchorに追加して、それを追加する必要があります
Anchorが別れているとカメラに反映されないので注意が必要でした
let worldAnchor = AnchorEntity(world: .zero)
worldAnchor.addChild(plane)
worldAnchor.addChild(camera)
worldAnchor.addChild(skybox)
worldAnchor.addChild(directionalLight)
arView.scene.anchors.append(worldAnchor)
その他
SceneEvents.Updateのタイミングでカメラを更新します
let len: Float = 0.8
var cameraRot: (yaw: Float, pitch: Float) = (yaw: 0, pitch: 0)
arView.scene
.publisher(for: SceneEvents.Update.self)
.sink { [weak self] (_: SceneEvents.Update) in
self?.updateEvent()
}
.store(in: &cancellables)
func updateEvent() {
camera.position = plane.position + .init(
x: len * sin(cameraRot.yaw) * cos(cameraRot.pitch),
y: len * sin(cameraRot.pitch),
z: len * cos(cameraRot.yaw) * cos(cameraRot.pitch)
)
camera.look(
at: plane.position,
from: camera.position,
relativeTo: nil
)
}
おわりに
RealityKitをnonARで使ってみました
SkyboxやカメラなどnonARで使うためのような機能もありますが、Lighting Shaderが設定できないなど、微妙に痒い所に手が届かない点があり、nonARモードでガッツリ使うには用途が限定される印象でした
しかし、RoomPlanなどAppleはARに力が入っているようなので、Frameworkの機能の追加、拡張に期待したいですしていたのですが、Vision Proが始まりReality Composerが使えなくなり、悲しい気持ちになりましたw