Q&A:visionOS向けアプリのビルド
2024年1月11日
過去数か月に開催された世界各地のApple Vision Proデベロッパラボで、AppleのエキスパートがvisionOSに関するさまざまな疑問にお答えしてきました。エンティティ、イマーシブ空間、コリジョンシェイプなどの新しい概念に関するインサイトを含む、よくある質問への回答を紹介します。
ジェスチャを使ってエンティティを操作するにはどうすればよいですか?
ジェスチャベースのエンティティインタラクションを有効にする場合、次の3つの重要な要素があります。
- エンティティにInputTargetComponent(英語)があること。これがないと、ジェスチャ入力が受信されません。
- エンティティにCollisionComponent(英語)があること。CollisionComponentの形状(英語)は、ジェスチャが実際にヒットする領域を定義するため、エンティティとのインタラクションのためにはコリジョンシェイプが適切に指定されていることが重要です。
- 使用するジェスチャは、操作の対象となるエンティティ(または任意のエンティティ)をターゲットに指定していること。以下はその例です。
private var tapGesture: some Gesture {
TapGesture()
.targetedToAnyEntity()
.onEnded { gestureValue in
let tappedEntity = gestureValue.entity
print(tappedEntity.name)
}
}
インタラクティブエンティティにHoverEffectComponent(英語)を提供することもお勧めです。これにより、ユーザーがエンティティを見たときにシステムが標準のハイライト効果をトリガできるようになります。
ウインドウグループ、イマーシブ空間、またはその両方を使用する必要がありますか?
アプリの特定の機能にどのシーンタイプを用いるかを決める際は、ウインドウ、ボリューム、イマーシブ空間の技術的な相違点を考慮してください。決定する際に考慮すべき、重要な技術的ないくつかの相違点は以下の通りです。
- イマーシブ空間が開いているとき、ユーザーが開いている別のアプリのウインドウとボリュームは非表示になる。
- ウインドウとボリュームでは、境界を超えるコンテンツがクリップされる。
- ウインドウとボリュームの配置は、ユーザーが完全にコントロールする。イマーシブ空間でのコンテンツの配置は、アプリが完全にコントロールする。
- ボリュームのサイズは固定されており、ウインドウのサイズは変更可能。
- ARKitは、オープンイマーシブ空間がある場合にのみアプリにデータを配信する。
Hello Worldのサンプルコード(英語)を確認し、visionOSの各シーンタイプの動作をよく理解しておきましょう。
シーンにおけるコリジョンシェイプを視覚化するにはどうすればよいですか?
「Debug Visualizations」メニューの「Collision Shapes debug visualization」を使用します。 このメニューではその他にも役立つデバッグビジュアリゼーション機能が多数あります。デバッグビジュアリゼーションについて詳しくは、実行中のアプリの外観に関する問題の診断(英語)をご参照ください。
SwiftUIビューをイマーシブ空間に配置できますか?
はい。offset(x:y:)(英語)およびoffset(z:)(英語)メソッドを使ってSwiftUIビューをイマーシブ空間に配置することができます。これらのオフセットはメートルではなくポイントで指定されることに注意してください。PhysicalMetric(英語)を利用してメートルをポイントに変換することができます。
RealityView内のエンティティを基準にSwiftUIビューを配置するにはどうすればよいですか?
RealityView attachments APIを用いてSwiftUIビューを作成し、ViewAttachmentEntityとしてアクセス可能にします。このエンティティはその他のエンティティと同様に、配置したり向きを変えたり、拡大・縮小したりすることができます。
RealityView { content, attachments in
// Fetch the attachment entity using the unique identifier.
let attachmentEntity = attachments.entity(for: "uniqueID")!
// Add the attachment entity as RealityView content.
content.add(attachmentEntity)
} attachments: {
// Declare a view that attaches to an entity.
Attachment(id: "uniqueID") {
Text("My Attachment")
}
}
ウインドウをプログラムで配置することは可能ですか?
ウインドウの配置に使用できるAPIはありませんが、どのようなユースケースを検討されているか、ぜひお知らせください。機能改善リクエストとしてお送りいただければ幸いです。このトピックについて詳しくは、ウインドウの配置とサイズ設定(英語)をご参照ください。
ユーザーが何を見ているかを知る方法はありますか?
プライバシーとユーザー設定のベストプラクティスの採用(英語)で説明されているように、システムではアプリに直接情報を渡すことなくカメラとセンサーの入力を処理しています。正確な目の動きや正確な視線の情報を取得する方法はありません。その代わりに、ユーザーが操作できるインターフェイス要素を作成し、システムに操作を管理させます。この方法では機能しないユースケースがあり、明示的な視線追跡を必要としない場合は、機能改善リクエストをお送りください。
visionOSでonHoverアクションとonContinuousHoverアクションが呼び出されるタイミングを教えてください。
onHover(英語)およびonContinuousHover(英語)アクションは、指がビュー上にホバーしているとき、または接続されたトラックパッドのポインタがビュー上にホバーしているときに呼び出されます。
アプリで独自のイマーシブ環境テクスチャを表示することはできますか?
アプリでImmersiveSpace(英語)が開かれている場合、UnlitMaterial(英語)で大きな球を作成し、内向きのジオメトリになるようスケールすることができます。
struct ImmersiveView: View {
var body: some View {
RealityView { content in
do {
// Create the sphere mesh.
let mesh = MeshResource.generateSphere(radius: 10)
// Create an UnlitMaterial.
var material = UnlitMaterial(applyPostProcessToneMap: false)
// Give the UnlitMaterial your equirectangular color texture.
let textureResource = try await TextureResource(named: "example")
material.color = .init(tint: .white, texture: .init(textureResource))
// Create the model.
let entity = ModelEntity(mesh: mesh, materials: [material])
// Scale the model so that it's mesh faces inward.
entity.scale.x *= -1
content.add(entity)
} catch {
// Handle the error.
}
}
}
}
既存のステレオビデオを持っていますが、MV-HEVCに変換するにはどうすればよいですか?
AVFoundation(英語)で、MV-HEVC形式でビデオを書き込むAPIが提供されています。
お持ちのビデオをMV-HEVC形式に変換するには次の手順に従います。
-
左ビューと右ビューのそれぞれでAVAsset(英語)を作成する。
-
AVOutputSettingsAssistant(英語)を使ってMV-HEVCで機能する出力設定を取得する。
-
水平方向の視差調整と視野(アセット固有)を指定する。以下に例を示します。
var compressionProperties = outputSettings[AVVideoCompressionPropertiesKey] as! [String: Any]
// Specifies the parallax plane.
compressionProperties[kVTCompressionPropertyKey_HorizontalDisparityAdjustment as String] = horizontalDisparityAdjustment
// Specifies the horizontal FOV (90 degrees is chosen in this case.)
compressionProperties[kCMFormatDescriptionExtension_HorizontalFieldOfView as String] = horizontalFOV
-
AVAssetWriter(英語)への入力として、AVAssetWriterInputTaggedPixelBufferGroupAdaptor(英語)を作成する。
-
左ビデオトラックと右ビデオトラックのそれぞれでAVAssetReader(英語)を作成する。
-
左右のトラックを読み取り、一致するサンプルをタグ付きピクセルバッファグループアダプタに下記のように追加する。
// Create a tagged buffer for each stereoView.
let taggedBuffers: [CMTaggedBuffer] = [
.init(tags: [.videoLayerID(0), .stereoView(.leftEye)], pixelBuffer: leftSample.imageBuffer!),
.init(tags: [.videoLayerID(1), .stereoView(.rightEye)], pixelBuffer: rightSample.imageBuffer!)
]
// Append the tagged buffers to the asset writer input adaptor.
let didAppend = adaptor.appendTaggedBuffers(taggedBuffers,
withPresentationTime: leftSample.presentationTimeStamp)
visionOSのRealityKitでシーンに光を当てるにはどうすればよいですか?
次の方法でvisionOSのRealityKitでシーンに光を当てることができます。
-
現実世界の環境に基づいて更新される、システム提供の自動照明環境を使用する。
-
ImageBasedLightComponentを通じて独自のイメージベースの照明を提供する。例を確認するには、新しいvisionOSアプリを作成し、Immersive Space RendererとしてRealityKitを選択し、Immersive Spaceとして「Full」を選択します。
visionOSではCustomMaterialがサポートされていないようですが、カスタムシェーディングを使ってマテリアルを作成する方法はありますか?
Reality Composer Proでは、Shader Graphを使ってカスタムシェーディングを備えたマテリアルを作成することができます。この方法で作成されたマテリアルは、アプリにShaderGraphMaterial(英語)としてアクセスすることができるため、コードでシェーダへの入力を動的に変更することができます。
Shader Graphに関する詳しい説明は、Reality Composer Proにおけるマテリアルの詳細(日本語字幕付き)をご参照ください。
デバイスの位置を基準にエンティティを配置するにはどうすればよいですか?
ImmersiveSpaceでは、queryDeviceAnchor(atTimestamp:)(英語)メソッドを使ってデバイスを完全に変換することができます。
visionOS向けのアプリ開発について詳しく
Q&A:visionOSの空間デザイン
View nowSpotlight on: Developing for visionOS
View nowSpotlight on: Developer tools for visionOS
View nowここで参照されたサンプルコードはApple Sample Code License(英語)にて提供されています。