SceneKit API リファレンスと移行マッピング
SceneKit の主要な概念すべてについて、RealityKit での相当機能を示す完全な API リファレンスです。
このリファレンスを使用する場面
次の場合に、このリファレンスを使用してください。
- 移行中に SceneKit → RealityKit の API 相当機能を調べる
- SceneKit の特定のクラスのプロパティやメソッドを確認する
- RealityKit に直接対応する SceneKit の機能を把握する
- シーングラフと ECS のアーキテクチャ上の違いを理解する
パート 1:SceneKit → RealityKit の概念マッピング
コアアーキテクチャ
| SceneKit | RealityKit | 備考 |
|---|
SCNScene | RealityViewContent / Entity(ルート) | RealityKit のシーンはエンティティ階層です |
SCNNode | Entity | どちらも軽量なコンテナーです |
SCNView | RealityView(SwiftUI) | iOS の UIKit では ARView を使用します |
SceneView(SwiftUI) | RealityView | SceneView は iOS 26 で非推奨です |
SCNRenderer | RealityRenderer | 低レベルの Metal レンダリング |
| ノードのプロパティ | コンポーネント | ECS ではデータと階層を分離します |
SCNSceneRendererDelegate | System / SceneEvents.Update | フレーム単位の更新 |
.scn ファイル | .usdz / .usda ファイル | xcrun scntool で変換します |
ジオメトリとレンダリング
| SceneKit | RealityKit | 備考 |
|---|
SCNGeometry | MeshResource | RealityKit ではコードから生成するか、USD を読み込みます |
SCNBox、SCNSphere など | MeshResource.generateBox()、.generateSphere() | 同様の組み込み形状 |
SCNMaterial | SimpleMaterial、PhysicallyBasedMaterial | RealityKit では PBR が基本です |
SCNMaterial.lightingModel = .physicallyBased | PhysicallyBasedMaterial | RealityKit ではデフォルトです |
SCNMaterial.diffuse | PhysicallyBasedMaterial.baseColor | プロパティ名が異なります |
SCNMaterial.metalness | PhysicallyBasedMaterial.metallic | プロパティ名が異なります |
SCNMaterial.roughness | PhysicallyBasedMaterial.roughness | 同じ概念です |
SCNMaterial.normal | PhysicallyBasedMaterial.normal | 同じ概念です |
| シェーダーモディファイア | ShaderGraphMaterial / CustomMaterial | 直接移植できないため、書き直しが必要です |
SCNProgram(カスタムシェーダー) | Metal 関数を使用する CustomMaterial | API の構成が異なります |
SCNGeometrySource | MeshResource.Contents | 低レベルのメッシュデータ |
トランスフォームと階層
| SceneKit | RealityKit | 備考 |
|---|
node.position | entity.position | どちらも SCNVector3 / SIMD3 です |
node.eulerAngles | entity.orientation(クォータニオン) | RealityKit ではクォータニオンが優先されます |
node.scale | entity.scale | どちらも SIMD3 です |
node.transform | entity.transform | 4×4 行列 |
node.worldTransform | entity.transform(relativeTo: nil) | ワールド空間のトランスフォーム |
node.addChildNode(_:) | entity.addChild(_:) | 同じ階層の概念です |
node.removeFromParentNode() | entity.removeFromParent() | 同じ概念です |
node.childNodes | entity.children | 子のコレクション |
node.parent | entity.parent | 親への参照 |
node.childNode(withName:recursively:) | entity.findEntity(named:) | 名前による検索 |
ライティング
| SceneKit | RealityKit | 備考 |
|---|
SCNLight(.omni) | PointLightComponent | 点光源 |
SCNLight(.directional) | DirectionalLightComponent | 太陽光/指向性ライト |
SCNLight(.spot) | SpotLightComponent | 円錐状のライト |
SCNLight(.area) | 直接相当する機能なし | 複数の点光源を使用します |
SCNLight(.ambient) | EnvironmentResource(IBL) | イメージベースドライティングが推奨されます |
SCNLight(.probe) | EnvironmentResource | 環境プローブ |
SCNLight(.IES) | 直接相当する機能なし | ライトの強度プロファイルを使用します |
カメラ
| SceneKit | RealityKit | 備考 |
|---|
SCNCamera | PerspectiveCamera entity | カメラコンポーネントを持つエンティティ |
camera.fieldOfView | PerspectiveCameraComponent.fieldOfViewInDegrees | 同じ概念 |
camera.zNear / camera.zFar | PerspectiveCameraComponent.near / .far | クリッピング平面 |
camera.wantsDepthOfField | ポストプロセスエフェクト | 仕組みが異なります |
camera.motionBlurIntensity | ポストプロセスエフェクト | 仕組みが異なります |
allowsCameraControl | カスタムジェスチャー処理 | 組み込みのオービットカメラはありません |
物理演算
| SceneKit | RealityKit | 備考 |
|---|
SCNPhysicsBody | PhysicsBodyComponent | コンポーネントベースです |
.dynamic | .dynamic | 同じモード |
.static | .static | 同じモード |
.kinematic | .kinematic | 同じモード |
SCNPhysicsShape | CollisionComponent / ShapeResource | RealityKitではボディとは別です |
categoryBitMask | CollisionGroup | 生のビットマスクではなく、名前付きグループです |
collisionBitMask | CollisionFilter | フィルターベースです |
contactTestBitMask | CollisionEvents.Began subscription | イベントベースの接触判定 |
SCNPhysicsContactDelegate | scene.subscribe(to: CollisionEvents.Began.self) | Combineスタイルのイベント |
SCNPhysicsField | PhysicsBodyComponent の力 | 力を直接適用します |
SCNPhysicsJoint | PhysicsJoint | 類似したジョイントタイプ |
アニメーション
| SceneKit | RealityKit | 備考 |
|---|
SCNAction | entity.move(to:relativeTo:duration:) | トランスフォームのアニメーション |
SCNAction.sequence | アニメーションの連結 | RealityKitでは宣言的ではありません |
SCNAction.group | 並列アニメーション | 異なるエンティティに適用します |
SCNAction.repeatForever | AnimationPlaybackController repeat | APIが異なります |
SCNTransaction (implicit) | 直接対応するものはありません | 明示的なアニメーションのみです |
CAAnimation bridge | entity.playAnimation() | USDから読み込みます |
SCNAnimationPlayer | AnimationPlaybackController | 再生制御 |
| モーフターゲット | USDのブレンドシェイプ | USDファイル経由で読み込みます |
インタラクション
| SceneKit | RealityKit | 備考 |
|---|
hitTest(_:options:) | RealityViewContent.entities(at:) | APIが異なります |
| SCNView上のジェスチャーレコグナイザー | ManipulationComponent | ドラッグ/回転/スケール変更機能を内蔵 |
allowsCameraControl | カスタム実装 | 組み込みのオービット機能はありません |
AR統合
| SceneKit | RealityKit | 備考 |
|---|
ARSCNView | RealityView + AnchorEntity | レガシー → モダン |
ARSCNViewDelegate | AnchorEntity の自動トラッキング | イベント駆動型 |
renderer(_:didAdd:for:) | AnchorEntity(.plane) | 宣言的なアンカリング |
ARWorldTrackingConfiguration | SpatialTrackingSession | iOS 18以降 |
パート2:シーングラフAPI
SCNScene
// Loading
let scene = SCNScene(named: "scene.usdz")!
let scene = try SCNScene(url: url, options: [
.checkConsistency: true,
.convertToYUp: true
])
// Properties
scene.rootNode // Root of node hierarchy
scene.background.contents // Skybox (UIImage, UIColor, MDLSkyCubeTexture)
scene.lightingEnvironment.contents // IBL environment map
scene.fogStartDistance // Fog near
scene.fogEndDistance // Fog far
scene.fogColor // Fog color
scene.isPaused // Pause simulation
SCNNode
// Creation
let node = SCNNode()
let node = SCNNode(geometry: SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0))
// Transform
node.position = SCNVector3(x, y, z)
node.eulerAngles = SCNVector3(pitch, yaw, roll)
node.scale = SCNVector3(1, 1, 1)
node.simdPosition = SIMD3<Float>(x, y, z) // SIMD variants available
node.pivot = SCNMatrix4MakeTranslation(0, -0.5, 0) // Offset pivot point
// Visibility
node.isHidden = false
node.opacity = 1.0
node.castsShadow = true
node.renderingOrder = 0 // Lower = rendered first
// Hierarchy
node.addChildNode(child)
node.removeFromParentNode()
node.childNodes
node.childNode(withName: "name", recursively: true)
node.enumerateChildNodes { child, stop in }
パート3:マテリアル
ライティングモデル
| モデル | 説明 | 用途 |
|---|
.physicallyBased | PBRの金属度・粗さモデル | リアルなレンダリング(推奨) |
.blinn | Blinn-Phong鏡面反射 | シンプルな光沢のある表面 |
.phong | Phong鏡面反射 | 従来の鏡面ハイライト |
.lambert | 拡散反射のみ、鏡面反射なし | マットな表面 |
.constant | ライティングなし、フラットカラー | UI要素、デバッグ用の可視化 |
.shadowOnly | 目に見えず、影を受け取る | ARの地面 |
マテリアルのプロパティ
let mat = SCNMaterial()
mat.lightingModel = .physicallyBased
// Textures or scalar values
mat.diffuse.contents = UIImage(named: "albedo") // Base color
mat.metalness.contents = 0.0 // 0 = dielectric, 1 = metal
mat.roughness.contents = 0.5 // 0 = mirror, 1 = rough
mat.normal.contents = UIImage(named: "normal") // Normal map
mat.ambientOcclusion.contents = UIImage(named: "ao") // AO map
mat.emission.contents = UIColor.blue // Glow
mat.displacement.contents = UIImage(named: "height") // Height map
// Options
mat.isDoubleSided = false // Render both sides
mat.writesToDepthBuffer = true
mat.readsFromDepthBuffer = true
mat.blendMode = .alpha // .add, .subtract, .multiply, .screen
mat.transparencyMode = .aOne // .rgbZero for pre-multiplied alpha
パート4:物理演算
ボディタイプとプロパティ
// Dynamic body with custom shape
let shape = SCNPhysicsShape(geometry: SCNSphere(radius: 0.5), options: nil)
let body = SCNPhysicsBody(type: .dynamic, shape: shape)
body.mass = 1.0
body.friction = 0.5
body.restitution = 0.3 // Bounciness
body.damping = 0.1 // Linear damping
body.angularDamping = 0.1 // Angular damping
body.isAffectedByGravity = true
body.allowsResting = true // Sleep optimization
node.physicsBody = body
// Compound shapes
let compound = SCNPhysicsShape(shapes: [shape1, shape2],
transforms: [transform1, transform2])
// Concave (static only)
let concave = SCNPhysicsShape(geometry: mesh, options: [
.type: SCNPhysicsShape.ShapeType.concavePolyhedron
])
ジョイントタイプ
| ジョイント | 説明 |
|---|
SCNPhysicsHingeJoint | 単一軸の回転(ドア) |
SCNPhysicsBallSocketJoint | 点を中心とした自由回転(振り子) |
SCNPhysicsSliderJoint | 軸に沿った直線運動(引き出し) |
SCNPhysicsConeTwistJoint | 制限付き回転(ラグドールの四肢) |
パート5:アニメーションAPI
SCNAction カタログ
| カテゴリ | アクション |
|---|
| 移動 | move(by:duration:)、move(to:duration:) |
| 回転 | rotate(by:around:duration:)、rotateTo(x:y:z:duration:) |
| スケール | scale(by:duration:)、scale(to:duration:) |
| フェード | fadeIn(duration:)、fadeOut(duration:)、fadeOpacity(to:duration:) |
| 表示状態 | hide()、unhide() |
| オーディオ | playAudio(source:waitForCompletion:) |
| カスタム | run { node in }、customAction(duration:action:) |
| 合成 | sequence([])、group([])、repeat(_:count:)、repeatForever(_:) |
| 制御 | wait(duration:)、removeFromParentNode() |
タイミング関数
action.timingMode = .linear // Default
action.timingMode = .easeIn // Slow start
action.timingMode = .easeOut // Slow end
action.timingMode = .easeInEaseOut // Slow start and end
action.timingFunction = { t in // Custom curve
return t * t // Quadratic ease-in
}
パート 6:制約
| 制約 | 目的 |
|---|
SCNLookAtConstraint | ノードを常にターゲットに向けます |
SCNBillboardConstraint | ノードを常にカメラに向けます |
SCNDistanceConstraint | 最小/最大距離を維持します |
SCNReplicatorConstraint | ターゲットのトランスフォームをコピーします |
SCNAccelerationConstraint | トランスフォームの変化を滑らかにします |
SCNSliderConstraint | 軸上に固定します |
SCNIKConstraint | 逆運動学チェーン |
let lookAt = SCNLookAtConstraint(target: targetNode)
lookAt.isGimbalLockEnabled = true // Prevent roll
lookAt.influenceFactor = 0.8 // Partial constraint
node.constraints = [lookAt]
RealityKit の場合:直接的な制約システムはありません。System の更新ロジック、または entity.look(at:from:relativeTo:) を使って実装します。
パート 7:シーン構成
SCNView の構成
| プロパティ | デフォルト | 説明 |
|---|
antialiasingMode | .multisampling4X | MSAA レベル |
preferredFramesPerSecond | 60 | 目標フレームレート |
allowsCameraControl | false | 組み込みのオービット/パン/ズーム |
autoenablesDefaultLighting | false | ライトがない場合にデフォルトのライトを追加します |
showsStatistics | false | FPS/ノード数/描画数のオーバーレイ |
isTemporalAntialiasingEnabled | false | TAA によるスムージング |
isJitteringEnabled | false | TAA 用の時間的ジッター |
debugOptions | [] | .showPhysicsShapes、.showBoundingBoxes、.renderAsWireframe |
リソース
WWDC:2014-609、2014-610、2017-604、2019-612
ドキュメント:/scenekit、/scenekit/scnscene、/scenekit/scnnode、/scenekit/scnmaterial、/scenekit/scnphysicsbody、/scenekit/scnaction
スキル:axiom-scenekit、axiom-realitykit、axiom-realitykit-ref