ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
RealityKit Traceについて
RealityKit Traceを使用して空間コンピューティングアプリのパフォーマンスを向上させる方法を確認しましょう。このプラットフォームのパフォーマンスプロファイリングに関するガイダンスと、RealityKit Traceテンプレートを使ってアプリのレンダリングを最適化する方法を学びます。また、アプリ内のさまざまなタイプのコンテンツをプロファイリングして、パフォーマンスの問題を特定するためのガイダンスも紹介します。
関連する章
- 0:44 - Rendering
- 2:17 - Profiling spatial apps
- 3:34 - Introduction to RealityKit Trace
- 7:38 - Optimizing offscreen passes
- 11:30 - Optimizing asset rendering
- 14:02 - Optimizing system power impact
- 17:55 - Overview of optimized World app
- 19:01 - Recommendations
リソース
関連ビデオ
WWDC23
- 空間コンピューティングのためのアプリのパワーと性能の最適化
- 空間コンピューティング向けのアプリ構築のための準備
- Instrumentsによるハング分析
- Reality Composer Proについて
WWDC21
Tech Talks
-
ダウンロード
♪ 心地よいヒップホップ音楽 ♪ ♪ こんにちは Sarinaです RealityKit Toolsチームの ソフトウェアエンジニアです Harjasです プロファイリングツールエンジニアです 今日はInstrumentsの RealityKit Trace テンプレートが 空間エクスペリエンスの パフォーマンスを最適化するのに どう役立つかを説明します 空間コンピューティングにおける ユーザーエクスペリエンスには パフォーマンスが不可欠です 空間エクスペリエンスを 最適化する方法を学ぶために このプラットフォームの レンダリングの仕組みについて 簡単に説明し Instrumentsで RealityKit Traceテンプレートを使い プロファイリングする方法を示します コンテンツを最適化するために利用できる 他の優れたツールについても 簡単に説明します このプラットフォームには 固有のパフォーマンス制約があります これらを理解するには まずレンダリングの仕組みを 理解する必要があります レンダリングには アプリのプロセス レンダリングサーバー コンポジターがあります アプリがこれらのコンポーネントと どのように相互作用するかは 作成するエクスペリエンス の種類によって異なります 空間アプリ用に作成できる エクスペリエンスの種類と それらがどのように レンダリングされるかを見てみましょう プラットフォーム上のアプリは 共有スペースまたはフルスペースに 入ることができます これらはレンダーのされ方によって 考慮すべきパフォーマンスに さまざまな影響を及ぼします 複数のアプリを並行して実行すると それらはすべて同じ空間 にレンダリングされます これが私たちがそれを 共有スペースと呼ぶ理由の1つです これはアプリのパフォーマンスが 他のアプリをレンダリングするよう サーバーが実行している作業の影響を受ける 可能性があることを意味します 次にレンダーサーバー がコンポジターと連携して 最終フレームを生成します アプリがFull Spaceに入ると 他の表示されているアプリは すべて非表示になります これはアプリのパフォーマンスが 現在非表示になっているアプリの レンダリング作業の影響を 受けなくなることを 意味しています フルスペースに入る方法の詳細については セッション「Go beyond the window with SwiftUI」をチェックしてください これまで説明した内容に基づいて アプリのプロファイリングに 推奨される方法が2つあります パフォーマンスの問題を調査したり システム電力への影響を 分析したりするときは常に アプリを個別にプロファイリングして アプリがシステムパフォーマンス に与える影響を理解します アプリが他のアプリと連携して 動作することが期待される場合は アプリを他のアプリとともに プロファイリングする必要があります これはユーザーがアプリを どのように体験するかを 理解するために重要です 空間アプリをプロファイリングして RealityKit Traceテンプレートを使用し アプリのパフォーマンスを 個別に最適化する方法を示しましょう 私たちはHello Worldの 開発に取り組んでおり パフォーマンスに問題がないことを 確認したいと考えています これはアプリのスタート画面で SwiftUI Viewです このビューには「Orbit内のオブジェクト」 ボタンがあります そのボタンをタップすると 地球を周回する物体について 詳しく知ることができます ボタンをクリックすると 地球の周りを周回している さまざまな天体の例をリストする 新しいビューが開きます このビューには次のようなオブジェクトの 3Dモデルが含まれています 月や 望遠鏡です このビューにはView Orbits (軌道を表示する)ボタンもあります ボタンをタップすると イマーシブなエクスペリエンスが開きます 地球とその周りを周回する衛星 これらのモデルには 詳細なアセットが使用されており このアプリのパフォーマンスに 影響を与えていると思われます イマーシブな体験では 地球を周回する衛星の軌跡が アニメーションで表示されます 地球を拡大してさらに 詳しく見ることもできます このインタラクションはものすごく 途切れ途切れなので ここにパフォーマンスの 問題があると思います Harjasと私は RealityKit Traceテンプレートを使い そのエクスペリエンスを プロファイリングしました Harjas 説明してもらえますか? もちろんです RealityKit Traceで利用できる すべての機能を見てみましょう RealityKit Traceは Instruments 15の 新しいテンプレートとして利用できます 実際のデバイスとシミュレータの 両方のプロファイリングに使用できます 最も正確で実用的な情報を取得するには 実際のデバイスのプロファイリングを行う 必要があります シミュレータに対して プロファイリングを行う場合 Macとオンデバイス間の ハードウェアとソフトウェアの違いのため すべてのタイミング情報が 正確であるとは限りません ただし素早い反復や 時間に基づいていない 一部の統計の改善には 引き続き使用できます RealityKit Traceテンプレートには いくつかの計測器が含まれています 最初に見ていきたいのは RealityKit Frames Instrumentです このデバイスはデバイスによって レンダリングされている 各フレームを追跡します これらのフレームを拡大して 各フレームのレンダリングに かかった時間を確認できます これによりフレームの 各ステージのレンダリングに かかった時間を確認できます これによりレンダーパイプラインの どの部分が原因で パフォーマンスの問題が発生する 可能性があるかの概要がわかります スムーズなユーザーエクスペリエンスを 実現するには アプリが1秒あたり 90フレームを達成する必要があります ただしOSが常に90fpsを 目標にしているわけではありません 表示されているコンテンツと デバイスの環境に最も適した フレームレートでレンダリングします フレームレートは 変更する可能性があるため すべてのフレームには レンダリングの完了期限があり デバイスが現在のターゲットフレーム レートに到達できるようにします フレームは3つのグループに分類されます 期限内にうまく完了しているフレーム 期限内にぎりぎりで完了しているフレーム フレームが期限を過ぎて実行され フレームドロップが発生しているフレーム これらの分類はそれぞれ緑 オレンジ 赤に色分けされています 期限を過ぎて実行されるフレームは ユーザーエクスペリエンスに 悪影響を及ぼします ズームアウトして 上からフレームを確認すると 色分けされているため トレースの問題のある部分を すぐに見つけることができます したがってパフォーマンス調査を 最もフレームドロップが発生している 領域に絞り込むことができます 個々のフレームに加えて このデバイスは システムがCPUまたは GPUの作業に費やした 平均時間も視覚化し 各フレームをレンダリングします 次にチェックしたいのは RealityKit Metricsです トップレベルではデバイスは検出した すべてのボトルネックを抽出します これらのボトルネックは レンダーパイプライン全体からの 包括的なタイミング情報を 調べることで生成されます フレームが期限を超えると 同時に発生する ボトルネックを優先します 以下の詳細ビューでは RealityKitのボトルネックが 重大度および種類ごとに まとめられているのがわかります さらに掘り下げて デバイスが発見したボトルネックの種類と 全体的なパフォーマンスへの影響を 正確に確認できます 拡張詳細ビューでは デバイスはこれらのボトルネックを さらに診断する方法と それらを軽減するために 実行できる手順についての 推奨事項を提供します RealityKit Metrics トラックを展開すると レンダーパイプラインの さまざまなコンポーネントから 数種類のメトリックスが表示されます これらの統計は アプリが提示するシーンの 完全な複雑さを理解するのに役立ちます 主要なメトリックスの一部には それらのメトリックスに対する 合理的な期待を知るのに役立つ しきい値が関連付けられています メトリックスを使用すると ボトルネックや フレームが期限に間に合わない理由 などの診断に役立ちます RealityKit Metricsは各フレームに どれだけの時間が 費やされているかを視覚化し アプリのRealityKit システムを実行します これにはすべての組み込みシステムと アプリが実装する すべてのカスタムシステムが含まれます この情報はTime Profilerと 組み合わせるのが最適で RealityKitシステムコードを 最適化できます 最後にRealityKitメトリックスに 表示されている システム電力影響レーンを確認して 素晴らしく一貫した ユーザーエクスペリエンスを 提供するために アプリが動作する必要がある パワーエンベロープを理解します ここで私たちが世界の体験中間に取った いくつかのトレースを見てみましょう アプリの最初のシーンはSwiftUIで 実装されたスタート画面でした フレーム計測ではこのトレース全体で かなりの数のフレームが ドロップされています これらのフレーム落ちは 重要ではないように見えますが ユーザーエクスペリエンスに 大きな損害を与える可能性があります Optionキーを押しながらドラッグすると より問題のある分野の1つに ズームインできます 時間範囲を調整することで 長時間実行フレーム中に RealityKit Metrics Instrumentが検出した ボトルネックを確認できます Instrumentsは 今回の最大のボトルネックが コアアニメーション エンコーディングであることを発見しました そこでコアアニメーションの 統計を確認してみます この統計は の 横にある開閉用三角ボタンをクリックし ラベルの付いたトラックを 選択すると表示されます これらのコアアニメーションメトリックスは フレームドロップの原因を 知るのに役立ちます メトリックスを調査すると その一部が メトリックスがどれほど深刻であるかの コンテキストを把握していることに 気づくでしょう タイムラインでは これが色分けに反映されます これは主要なメトリックスの 適切なしきい値を示すためのものです タイムラインの視覚化に基づいて アプリが オフスクリーン準備数の推奨しきい値を 超えているのは明らかです 下部の概要は ここで準備されるオフスクリーンの平均数が 180であることを示しています これはかなり高い平均値です コアアニメーションの統計を 検討する場合 留意すべき作業の種類が3つあります まず透明度とぼかし効果は システムにとって 非常に高コストな操作です これらのエフェクトはユーザーに 最も大きな影響を与える場合に限定し それ以外では控えめに使用します レンダーパスの数は レイヤーの数によって決まります コアアニメーションは画像全体を 個別にレンダリングする必要があります そして最後に オフスクリーンパスがあります 名前が示すように オフスクリーンパスは オフスクリーンで レンダリングされるレンダーパスで ディスプレイ用ではありません オフスクリーンパスでは レンダリングパスが 現在実行していることを 一時停止する必要があり ユーザーには表示されない 作業を実行します ただし通常の レンダリングパスを続行するには オフスクリーンパスの出力が必要です オフスクリーンパスは 特に空間アプリに 影響を与えます 他のアプリプラットフォームとは異なり このプラットフォームは 空間アプリを継続的に レンダリングします あらゆるフレームは ユーザーの頭の動きなどの 環境要因を考慮する必要があります したがって静的UIは システムのターゲットフレームレートで レンダリングできるほど 効率的である必要があります オフスクリーンパスを引き起こす 可能性のある作業には 主に4つのタイプがあります シャドウ マスキング 角丸長方形と 視覚効果です オフスクリーン パスについて詳しくは Tech Talksの 「Demystify and eliminate hitches in the render phase」をご覧ください オフスクリーンパスが多かったので このビューのSwiftUIコードを チェックして その原因を特定します SwiftUIコードでは このビューはマスキングや 視覚効果を実行しません ただしシャドウが適用される例もあります たとえばSwiftUI View アイテムでは いくつかのボタンに シャドウが適用されています シャドウは特に 透明性と組み合わせた場合 特にコストが高い操作です シャドウは便利なUIイディオムですが 空間アプリの場合は ユーザーに重大な効果をもたらしたとき シャドウを使用する必要があります これらのシャドウを無効にして 新しいトレースを見てみましょう シャドウを無効にした状態で RealityKit Frames Instrumentで フレームの問題はほとんどなく RealityKit Metricsでは オフスクリーンパスが4分の1に 減少したと報告しています Worldアプリで見た次のシーンは 軌道ビュー内のオブジェクトです そのシーンからトレースを開いて 最適化できるものがないかどうか 確認するつもりです Frames Instrumentでは ドロップされたフレームが散在し トレース全体に ボトルネックがたくさんあります RealityKitメトリックスの 詳細ビューには これらのボトルネックの 概要が表示されます
要約すると これらのボトルネックのほとんどは GPUワークストールに関連しています 最も頻繁に報告される ボトルネックのタイプは GPUストールであるため 再びRealityKit Metrics を拡張していきます ただし今回は3Dレンダートラックを 使用して調査します
フレームドロップの数が多い トレース領域を選択します この時間選択では 3Dレンダリングメトリックスは 三角形と頂点数が 推奨しきい値をはるかに超えています 次にフレームドロップがほとんどない トレース領域を強調表示します
レンダリングメトリックスによると 三角形と頂点の数は 推奨しきい値内にあります これはアプリがシーン内で使用する アセットの数と品質を 実際に評価する必要が あることを意味します アセットのレンダリングを最適化するときは RealityKitメトリックスでまず 三角形と頂点を確認し 3Dレンダリンググループからの 描画呼び出しを確認します これらのメトリックスを最適化するには 可能な限り単純な形状の メッシュを使用します 同じメッシュのアセットを利用する場合は インスタンス化を活用してください 新しいメトリックスツールである Reality Composer Proの 統計を使用して アセットの複雑さをチェックします これにより3Dコンテンツを組み立て 編集しプレビューできます そのコンテンツは後で Xcodeプロジェクトのコードを通じて 直接アクセスできます このツールの詳細と優れた アセットの作成方法については 「Meet Reality Composer Pro」 セッションをチェックしてください 先に進んで使用していたアセットを 使用するポリゴンが 少ないアセットと交換し 新たなトレースを捉えました このトレースでは Frames Instrumentは すべてのフレームが 期限に達していることを報告します そして3Dレンダリング統計 をもう一度確認すると
三角形と頂点の数が 大幅に減少していることが 報告されています これらのアセットでは 使用するポリゴンの数が減りましたが エクスペリエンスの品質は 低下しませんでした 次のトレースは地球モデルと インタラクションしていたときのものです このシーンでは 地球のサイズを変更するのが 実際にはかなり不安定でした RealityKit Metricsは システム電力影響レーンが かなりの時間にわたって 非常に高かったと報告しています これはアプリの一部が 非常に非効率であり ユーザーエクスペリエンスが影響を受ける 可能性があります 可能な限り通常の状態で デバイスのシステム電力への 影響を維持し アプリが適切に 動作することを目標にする 必要があります システム電力への影響を軽減するために プロファイリングを行う場合は 常にアプリを分離して プロファイリングを行い 最も実用的な情報を 確実に入手できるようにします いくつかの方法を使用して システム電力への影響を軽減できます まずRealityKit Metricsの 統計が想定内であることを確認します これらが予想を超えている場合 デバイスは長時間にわたって スムーズな体験を提供するために より高い電力状態で動作します 次にCPUとGPUがどのような 作業を行っているかを確認します CPUについては高電力描画領域中に Time Profilerが高いCPU使用率を 報告するかどうかを確認します その場合はTime Profilerを 使用しながら CPUバウンドのコードを最適化します GPUにはパフォーマンス状態があります GPUが最大段階にあるとき かなりの量の電力が消費されます その場合 InstrumentsのMetal System Traceテンプレートを使用して GPUでどのような作業が行われているかを 確認する必要があります そうすることで何を 最適化できるか理解できます トレースを遡ってみると Time Profilerは この領域のCPU使用率が 平均100%であることを示しており この時間のほとんどにおいて GPUパフォーマンス状態は最小でした Time Profiler を使用するとCPU 使用率が高くなる原因を確認できます 最も重いスタックトレースは 拡張詳細ビューにあります これはコールツリー内のコードの 最も高コストなパーツを 素早く見つけることができるため Time Profilerの 非常に便利な機能です これらのフレームを見ると Entity.makeModelが 大量のCPU時間を 使用していることがわかります 次のフレームではEntity.generate CollisionShapesを呼び出します したがってパフォーマンスの 問題はモデルと衝突形状を 絶えず生成することが 原因であると考えられます これは高コストな操作です Xcodeを開き これについて何ができるか確認します これはコールツリーで多くのCPU時間を 消費していることを示した Entity.makeModel 関数呼び出しです これはmakeGlobe関数内で 呼び出されます Controlキーを押しながら makeGlobe関数をクリックし それを呼び出している元を確認します Orbit SwiftUIビュー 本体から呼び出されます ビュー本体を非常に迅速に 計算する必要があるため これは避けるべきアンチパターンです SwiftUIビュー本体で モデルの読み込みや その他のコストのかかる操作は 避けてください ビューの状態が変わるたびに これらの高コストな操作は すべて再計算する必要があるからです 私がやろうとしていることは ビュー本体から この呼び出しを削除することです 次にViewModelに Earthエンティティの 再利用可能なバージョンを追加します 最後に再利用可能な Earthエンティティを Orbit Viewで使用します これでビュー本体が再計算されるときに アプリは同じモデルの再読み込みに 時間を無駄にすることがなくなりました 修正後のトレースを見ると 電力への影響が 公称状態に戻っています またTime Profilerは CPU使用率が100%から 10%に低下したことを報告します これらすべての最適化を行った後 ボトルネックは ほとんど報告されていません ほぼすべてのフレームが期限に達しており パワーは予想の範囲内です Worldアプリはこのプラットフォーム用に よく最適化されたアプリになりました オフスクリーンパスの数が減ったので ハイポリゴンのアセットを 合理的なアセットに置き換え CPUと電力の使用量を削減するため このアプリの最適化されたバージョンを 段階的に実行していきます スタート画面は素晴らしく シャドウはユーザーエクスペリエンスに あまり影響を与えていなかったので これは良い最適化でした 次にOrbit内の オブジェクトを開いてみましょう ポリゴンの少ないアセットを 使用しているにもかかわらず これらのモデルは見栄えがします その余分な詳細はリソースを 無駄にしているだけでした 最後に地球モデルを再度開いて サイズ変更を試みます
このインタラクションはバターのように スムーズになりました 以上がRealityKit Traceを使用して アプリをこの新しいプラットフォームに 最適化する方法の簡単な概要でした ところでSarina メトリックスが利用できる ツールは他に何がありますか? 空間コンピューティング向けに アプリを最適化するのに 役立つツールがいくつかあります SwiftUIコンテンツを最適化するには SwiftUIとコアアニメーションと ハングを分析するための Instrumentsアプリ内に ドメイン固有のツールがあります ハングについては 「Analyze hangs with Instruments」 セッションで詳しく学ぶことができます 3Dアセットベースの コンテンツを最適化する 利用可能なツールもいくつかあります Time Profiler Instrumentは アセットのロードに長い時間がかかるなど アプリが最も時間がかかっている 領域を見つけるのに役立ちます The RealityKit Metrics Instrumentは シーンにアセットが多すぎる場合や 複雑すぎるアセットの診断に役立ちます 最後にReality Composer Proを使って シーンを組み立てているときに アセットの複雑さをチェックできます Reality Composer Proについて詳しくは 「Meet Reality Composer Pro」 セッションをご覧ください アプリでMetalを使用している場合 最も便利なツールはInstrumentsの Metal System Traceテンプレートです このテンプレートにはGPUタイムライン GPUカウンターと GPUパフォーマンスステートなどの 主要なメトリックスが含まれています このテンプレートとMetalコンテンツの プロファイリングのための その他のツールの詳細については 「Discover Metal debugging, profiling, and asset creation tools」 セッションをご覧ください まとめると このプラットフォームには パフォーマンスが不可欠です 可能な限り最高のユーザー エクスペリエンスのために アプリを適切に最適化する必要があります RealityKit Trace テンプレートを使用して アプリ内のパフォーマンスの ボトルネックを見つけることができます 他のツールを使用して プロアクティブにプロファイリングし Reality Composer Pro でコンテンツをチェックすると パフォーマンスの問題を見つけて 解決するのにも役立ちます RealityKit Trace テンプレートを使用して アプリを最適化する方法の詳細については メトリックスドキュメントを ご確認ください パフォーマンスをより深く理解するために このプラットフォームについてのセッション 「Optimize app power and performance for spatial computing」 をご覧ください トレースがどのようなものであっても 空間コンピューティングアプリの 最適化をお楽しみください ご視聴ありがとうございます ♪
-
-
10:50 - SwiftUI View with High Offscreens
private struct Item: View { var module: Module // The corner radius of the item's hightlight when selected or hovering. let cornerRadius = 20.0 var body: some View { NavigationLink(value: module) { VStack(alignment: .leading, spacing: 3) { Text(module.eyebrow) .font(.titleHeading) .foregroundStyle(.secondary) VStack(alignment: .leading, spacing: 7) { Text(module.heading) .font(.largeTitle) Text(module.abstract) } } .padding(.horizontal, 5) .padding(.vertical, 20) } .buttonStyle(.bordered) .shadow(radius: 10) .buttonBorderShape(.roundedRectangle(radius: cornerRadius)) .frame(minWidth: 150, maxWidth: 280) } }
-
16:33 - EarthEntity Factory
class EarthEntity: Entity { static func makeGlobe() -> EarthEntity { EarthEntity(earthModel: Entity.makeModel( name: "Earth", filename: "Globe", radius: 0.35, color: .blue) ) } static func makeCloudyEarth() -> EarthEntity { let earthModel = Entity() earthModel.name = "Earth" Task { if let scene = await loadFromRealityComposerPro( named: WorldAssets.rootNodeName, fromSceneNamed: WorldAssets.sceneName ) { earthModel.addChild(scene) } else { fatalError("Unable to load earth model") } } return EarthEntity(earthModel: earthModel) } }
-
16:53 - Orbit SwiftUI View Body
struct Orbit: View { @EnvironmentObject private var model: ViewModel var body: some View { Earth( world: EarthEntity.makeGlobe(), earthConfiguration: model.orbitEarth, satelliteConfiguration: [model.orbitSatellite], moonConfiguration: model.orbitMoon, showSun: true, sunAngle: model.orbitSunAngle, animateUpdates: true ) .place( initialPosition: Point3D([475, -1200.0, -1200.0]), useCustomGesture: model.useCustomGesture, handOffset: model.customGestureHandOffset, isCustomGestureAnimated: model.isCustomGestureAnimated, debugCustomGesture: model.debugCustomGesture, scale: $model.orbitEarth.scale) } }
-
17:26 - SwiftUI ViewModel
class ViewModel: ObservableObject { // MARK: - Navigation @Published var navigationPath: [Module] = [] @Published var titleText: String = "" @Published var isTitleFinished: Bool = false var finalTitle: String = "Hello World" // MARK: - Globe @Published var globeEarthEntity: EarthEntity = .makeGlobe() @Published var isShowingGlobe: Bool = false @Published var globeEarth: EarthEntity.Configuration = .globeEarthDefault @Published var globeEarthOffset: SIMD3<Double> = [0, 0, 0] @Published var globePanelOffset: SIMD3<Double> = [0, -50, 30] @Published var showSatelliteButton: Bool = false @Published var isShowingSatellite: Bool = false // MARK: - Orbit @Published var orbitEarthEntity: EarthEntity = .makeGlobe() @Published var useCustomGesture: Bool = true @Published var customGestureHandOffset: SIMD3<Float> = [0, 0.21, -0.07] @Published var isCustomGestureAnimated: Bool = false @Published var debugCustomGesture: Bool = false @Published var orbitSatelliteScale: Float = 0.9 @Published var orbitMoonScale: Float = 0.9 @Published var orbitTelescopeScale: Float = 0.8 @Published var orbitSatelliteZOffset: Double = 100 @Published var orbitMoonZOffset: Double = 100 @Published var orbitTelescopeZOffset: Double = 100 @Published var isShowingOrbit: Bool = false @Published var orbitImmersionStyle: ImmersionStyle = .mixed @Published var orbitEarth: EarthEntity.Configuration = .orbitEarthDefault @Published var orbitSatellite: SatelliteEntity.Configuration = .orbitSatelliteDefault @Published var orbitMoon: SatelliteEntity.Configuration = .orbitMoonDefault @Published var orbitSunAngle: Angle = .degrees(150) var orbitSunAngleBinding: Binding<Float> { Binding<Float>( get: { Float(self.orbitSunAngle.degrees) }, set: { self.orbitSunAngle = .degrees(Double($0)) } ) } // MARK: - Solar System @Published var solarEarthEntity: EarthEntity = .makeCloudyEarth() @Published var isShowingSolar: Bool = false @Published var solarImmersionStyle: ImmersionStyle = .full @Published var solarEarth: EarthEntity.Configuration = .solarEarthDefault @Published var solarSatellite: SatelliteEntity.Configuration = .solarTelescopeDefault @Published var solarMoon: SatelliteEntity.Configuration = .solarMoonDefault @Published var solarSunDistance: Double = 700 @Published var solarSunAngle: Angle = .degrees(280) @Published var solarSunSpotIntensity: Float = 10.5 @Published var solarSunEmissionIntensity: Float = 10.5 var solarSunPosition: SIMD3<Float> { [Float(solarSunDistance * sin(solarSunAngle.radians)), 0, Float(solarSunDistance * cos(solarSunAngle.radians))] } }
-
17:33 - SwiftUI Orbit View Body
struct Orbit: View { @EnvironmentObject private var model: ViewModel var body: some View { Earth( world: model.globeEarthEntity, earthConfiguration: model.orbitEarth, satelliteConfiguration: [model.orbitSatellite], moonConfiguration: model.orbitMoon, showSun: true, sunAngle: model.orbitSunAngle, animateUpdates: true ) .place( initialPosition: Point3D([475, -1200.0, -1200.0]), useCustomGesture: model.useCustomGesture, handOffset: model.customGestureHandOffset, isCustomGestureAnimated: model.isCustomGestureAnimated, debugCustomGesture: model.debugCustomGesture, scale: $model.orbitEarth.scale) } }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。