SceneKit API 参考与迁移映射
SceneKit 完整 API 参考,涵盖所有主要概念及其对应的 RealityKit 等效项。
何时使用此参考
在以下情况下使用此参考:
- 迁移时查找 SceneKit → RealityKit API 等效项
- 检查特定 SceneKit 类的属性或方法
- 规划哪些 SceneKit 功能在 RealityKit 中有直接对应项
- 了解场景图与 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) | 无直接对应项 | 使用光照强度配置文件 |
Camera(相机)
| SceneKit | RealityKit | 说明 |
|---|
SCNCamera | PerspectiveCamera entity | 带有相机组件的实体 |
camera.fieldOfView | PerspectiveCameraComponent.fieldOfViewInDegrees | 相同概念 |
camera.zNear / camera.zFar | PerspectiveCameraComponent.near / .far | 裁剪平面 |
camera.wantsDepthOfField | 后期处理效果 | 机制不同 |
camera.motionBlurIntensity | 后期处理效果 | 机制不同 |
allowsCameraControl | 自定义手势处理 | 没有内置的环绕相机 |
Physics(物理)
| SceneKit | RealityKit | 说明 |
|---|
SCNPhysicsBody | PhysicsBodyComponent | 基于组件 |
.dynamic | .dynamic | 相同模式 |
.static | .static | 相同模式 |
.kinematic | .kinematic | 相同模式 |
SCNPhysicsShape | CollisionComponent / ShapeResource | 在 RealityKit 中与刚体分离 |
categoryBitMask | CollisionGroup | 命名组,而非原始位掩码 |
collisionBitMask | CollisionFilter | 基于筛选器 |
contactTestBitMask | CollisionEvents.Began 订阅 | 基于事件的接触 |
SCNPhysicsContactDelegate | scene.subscribe(to: CollisionEvents.Began.self) | 类似 Combine 的事件 |
SCNPhysicsField | PhysicsBodyComponent 力 | 直接施加力 |
SCNPhysicsJoint | PhysicsJoint | 关节类型相似 |
Animation(动画)
| SceneKit | RealityKit | 说明 |
|---|
SCNAction | entity.move(to:relativeTo:duration:) | 变换动画 |
SCNAction.sequence | 动画串联 | 在 RealityKit 中声明性较弱 |
SCNAction.group | 并行动画 | 应用于不同实体 |
SCNAction.repeatForever | AnimationPlaybackController 重复播放 | API 不同 |
SCNTransaction(隐式) | 无直接对应项 | 仅支持显式动画 |
CAAnimation 桥接 | entity.playAnimation() | 从 USD 加载 |
SCNAnimationPlayer | AnimationPlaybackController | 播放控制 |
| Morph targets(变形目标) | USD 中的 Blend shapes(混合形状) | 通过 USD 文件加载 |
Interaction(交互)
| SceneKit | RealityKit | 说明 |
|---|
hitTest(_:options:) | RealityViewContent.entities(at:) | API 不同 |
| SCNView 上的手势识别器 | ManipulationComponent | 内置拖动/旋转/缩放 |
allowsCameraControl | 自定义实现 | 没有内置的环绕功能 |
AR Integration(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