{"id":"6d4d612d-2aab-4080-a6d4-dd23ee820a13","shortId":"CSXEJS","kind":"skill","title":"scenekit","tagline":"Build 3D scenes and visualizations using SceneKit. Use when creating 3D views with SCNView and SCNScene, building node hierarchies with SCNNode, applying materials and lighting, animating with SCNAction, simulating physics with SCNPhysicsBody, loading 3D models (.usdz, .scn), add","description":"# SceneKit\n\nApple's high-level 3D rendering framework for building scenes and visualizations\non iOS using Swift 6.3. Provides a node-based scene graph, built-in geometry\nprimitives, physically based materials, lighting, animation, and physics.\n\n**Deprecation notice (WWDC 2025):** SceneKit is officially deprecated across all\nApple platforms and is now in maintenance mode (critical bug fixes only). Existing\napps continue to work. For new projects or major updates, Apple recommends\nRealityKit. See WWDC 2025 session 288 for migration guidance.\n\n## Contents\n\n- [Scene Setup](#scene-setup)\n- [Nodes and Geometry](#nodes-and-geometry)\n- [Materials](#materials)\n- [Lighting](#lighting)\n- [Cameras](#cameras)\n- [Animation](#animation)\n- [Physics](#physics)\n- [Particle Systems](#particle-systems)\n- [Loading Models](#loading-models)\n- [SwiftUI Integration](#swiftui-integration)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Scene Setup\n\n### SCNView in UIKit\n\n```swift\nimport SceneKit\n\nlet sceneView = SCNView(frame: view.bounds)\nsceneView.scene = SCNScene()\nsceneView.allowsCameraControl = true\nsceneView.autoenablesDefaultLighting = true\nsceneView.backgroundColor = .black\nview.addSubview(sceneView)\n```\n\n`allowsCameraControl` adds built-in orbit, pan, and zoom gestures. Typically\ndisabled in production where custom camera control is needed.\n\n### Creating an SCNScene\n\n```swift\nlet scene = SCNScene()                                          // Empty\nguard let scene = SCNScene(named: \"art.scnassets/ship.scn\")     // .scn asset catalog\n    else { fatalError(\"Missing scene asset\") }\nlet scene = try SCNScene(url: Bundle.main.url(                  // .usdz from bundle\n    forResource: \"spaceship\", withExtension: \"usdz\")!)\n```\n\n## Nodes and Geometry\n\nEvery scene has a `rootNode`. All content exists as descendant nodes. Nodes\ndefine position, orientation, and scale in their parent's coordinate system.\nSceneKit uses a right-handed coordinate system: +X right, +Y up, +Z toward\nthe camera.\n\n```swift\nlet parentNode = SCNNode()\nscene.rootNode.addChildNode(parentNode)\n\nlet childNode = SCNNode()\nchildNode.position = SCNVector3(0, 1, 0)  // 1 unit above parent\nparentNode.addChildNode(childNode)\n```\n\n### Transforms\n\n```swift\nnode.position = SCNVector3(x: 0, y: 2, z: -5)\nnode.eulerAngles = SCNVector3(x: 0, y: .pi / 4, z: 0)  // 45-degree Y rotation\nnode.scale = SCNVector3(2, 2, 2)\nnode.simdPosition = SIMD3<Float>(0, 2, -5)  // Prefer simd for performance\n```\n\n### Built-in Primitives\n\n`SCNBox`, `SCNSphere`, `SCNCylinder`, `SCNCone`, `SCNTorus`, `SCNCapsule`,\n`SCNTube`, `SCNPlane`, `SCNFloor`, `SCNText`, `SCNShape` (extruded Bezier path).\n\n```swift\nlet node = SCNNode(geometry: SCNSphere(radius: 0.5))\n```\n\n### Finding Nodes\n\n```swift\nlet maxNode = scene.rootNode.childNode(withName: \"Max\", recursively: true)\nlet enemies = scene.rootNode.childNodes { node, _ in\n    node.name?.hasPrefix(\"enemy\") == true\n}\n```\n\n## Materials\n\n`SCNMaterial` defines surface appearance. Use `firstMaterial` for single-material\ngeometries or the `materials` array for multi-material.\n\n### Color and Texture\n\n```swift\nlet material = SCNMaterial()\nmaterial.diffuse.contents = UIColor.systemBlue     // Solid color\nmaterial.diffuse.contents = UIImage(named: \"brick\") // Texture\nmaterial.normal.contents = UIImage(named: \"brick_normal\")\nsphere.firstMaterial = material\n```\n\n### Physically Based Rendering (PBR)\n\n```swift\nlet pbr = SCNMaterial()\npbr.lightingModel = .physicallyBased\npbr.diffuse.contents = UIImage(named: \"albedo\")\npbr.metalness.contents = 0.8       // Scalar or texture\npbr.roughness.contents = 0.2       // Scalar or texture\npbr.normal.contents = UIImage(named: \"normal\")\npbr.ambientOcclusion.contents = UIImage(named: \"ao\")\n```\n\n### Lighting Models\n\n`.physicallyBased` (metalness/roughness), `.blinn` (default), `.phong`,\n`.lambert` (diffuse-only), `.constant` (unlit), `.shadowOnly`.\n\nEach material property is an `SCNMaterialProperty` accepting `UIColor`,\n`UIImage`, `CGFloat` scalar, `SKTexture`, `CALayer`, or `AVPlayer`.\n\n### Transparency\n\n```swift\nmaterial.transparency = 0.5\nmaterial.transparencyMode = .dualLayer\nmaterial.isDoubleSided = true\n```\n\n## Lighting\n\nAttach an `SCNLight` to a node. The light's direction follows the node's\nnegative Z-axis.\n\n### Light Types\n\n```swift\n// Ambient: uniform, no direction\nlet ambient = SCNLight()\nambient.type = .ambient\nambient.color = UIColor(white: 0.3, alpha: 1)\n\n// Directional: parallel rays (sunlight)\nlet directional = SCNLight()\ndirectional.type = .directional\ndirectional.castsShadow = true\n\n// Omni: point light, all directions\nlet omni = SCNLight()\nomni.type = .omni\nomni.attenuationEndDistance = 20\n\n// Spot: cone-shaped\nlet spot = SCNLight()\nspot.type = .spot\nspot.spotInnerAngle = 20\nspot.spotOuterAngle = 60\n```\n\nAttach to a node:\n\n```swift\nlet lightNode = SCNNode()\nlightNode.light = directional\nlightNode.eulerAngles = SCNVector3(-Float.pi / 3, 0, 0)\nlightNode.position = SCNVector3(0, 10, 10)\nscene.rootNode.addChildNode(lightNode)\n```\n\n### Shadows\n\n```swift\nlight.castsShadow = true\nlight.shadowMapSize = CGSize(width: 2048, height: 2048)\nlight.shadowSampleCount = 8\nlight.shadowRadius = 3.0\nlight.shadowColor = UIColor(white: 0, alpha: 0.5)\n```\n\n### Category Bit Masks\n\n```swift\nlight.categoryBitMask = 1 << 1     // Category 2\nnode.categoryBitMask = 1 << 1      // Only lit by category-2 lights\n```\n\nSceneKit renders a maximum of 8 lights per node. Use `attenuationEndDistance`\non point/spot lights so SceneKit skips them for distant nodes.\n\n## Cameras\n\nAttach an `SCNCamera` to a node to define a viewpoint.\n\n```swift\nlet cameraNode = SCNNode()\ncameraNode.camera = SCNCamera()\ncameraNode.position = SCNVector3(0, 5, 15)\ncameraNode.look(at: SCNVector3Zero)\nscene.rootNode.addChildNode(cameraNode)\nsceneView.pointOfView = cameraNode\n```\n\n### Configuration\n\n```swift\ncamera.fieldOfView = 60                        // Degrees\ncamera.zNear = 0.1\ncamera.zFar = 500\ncamera.automaticallyAdjustsZRange = true\n\n// Orthographic\ncamera.usesOrthographicProjection = true\ncamera.orthographicScale = 10\n```\n\nDepth-of-field (`wantsDepthOfField`, `focusDistance`, `fStop`) and HDR effects\n(`wantsHDR`, `bloomIntensity`, `bloomThreshold`, `screenSpaceAmbientOcclusionIntensity`)\nare configured directly on `SCNCamera`.\n\n## Animation\n\nSceneKit provides three animation approaches.\n\n### SCNAction (Declarative, Game-Oriented)\n\nReusable, composable animation objects attached to nodes.\n\n```swift\nlet move = SCNAction.move(by: SCNVector3(0, 2, 0), duration: 1)\nlet rotate = SCNAction.rotateBy(x: 0, y: .pi, z: 0, duration: 1)\nnode.runAction(.group([move, rotate]))\n\n// Sequential\nnode.runAction(.sequence([.fadeOut(duration: 0.3), .removeFromParentNode()]))\n\n// Infinite loop\nlet pulse = SCNAction.sequence([\n    .scale(to: 1.2, duration: 0.5),\n    .scale(to: 1.0, duration: 0.5)\n])\nnode.runAction(.repeatForever(pulse))\n```\n\n### SCNTransaction (Implicit Animation)\n\n```swift\nSCNTransaction.begin()\nSCNTransaction.animationDuration = 1.0\nnode.position = SCNVector3(5, 0, 0)\nnode.opacity = 0.5\nSCNTransaction.completionBlock = { print(\"Done\") }\nSCNTransaction.commit()\n```\n\n### Explicit Animations (Core Animation)\n\n```swift\nlet animation = CABasicAnimation(keyPath: \"rotation\")\nanimation.toValue = NSValue(scnVector4: SCNVector4(0, 1, 0, Float.pi * 2))\nanimation.duration = 2\nanimation.repeatCount = .infinity\nnode.addAnimation(animation, forKey: \"spin\")\n```\n\n## Physics\n\n### Physics Bodies\n\n```swift\nnode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: nil)   // Forces + collisions\nfloor.physicsBody = SCNPhysicsBody(type: .static, shape: nil)    // Immovable\nplatform.physicsBody = SCNPhysicsBody(type: .kinematic, shape: nil) // Code-driven\n```\n\nWhen `shape` is `nil`, SceneKit derives it from geometry. For performance, use\nsimplified shapes:\n\n```swift\nlet shape = SCNPhysicsShape(\n    geometry: SCNBox(width: 1, height: 2, length: 1, chamferRadius: 0),\n    options: nil\n)\nnode.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)\nnode.physicsBody?.mass = 2.0\nnode.physicsBody?.restitution = 0.3\n```\n\n### Applying Forces\n\n```swift\nnode.physicsBody?.applyForce(SCNVector3(0, 10, 0), asImpulse: false) // Continuous\nnode.physicsBody?.applyForce(SCNVector3(0, 5, 0), asImpulse: true)   // Instant\nnode.physicsBody?.applyTorque(SCNVector4(0, 1, 0, 2), asImpulse: true)\n```\n\n### Collision Detection\n\n```swift\nstruct PhysicsCategory {\n    static let player:     Int = 1 << 0\n    static let enemy:      Int = 1 << 1\n    static let ground:     Int = 1 << 2\n}\n\nplayerNode.physicsBody?.categoryBitMask = PhysicsCategory.player\nplayerNode.physicsBody?.collisionBitMask = PhysicsCategory.ground | PhysicsCategory.enemy\nplayerNode.physicsBody?.contactTestBitMask = PhysicsCategory.enemy\n\nscene.physicsWorld.contactDelegate = self\n\nfunc physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {\n    handleCollision(between: contact.nodeA, and: contact.nodeB)\n}\n```\n\n### Gravity\n\n```swift\nscene.physicsWorld.gravity = SCNVector3(0, -9.8, 0)\nnode.physicsBody?.isAffectedByGravity = false\n```\n\n## Particle Systems\n\n`SCNParticleSystem` creates effects like fire, smoke, rain, and sparks.\n\n```swift\nlet particles = SCNParticleSystem()\nparticles.birthRate = 100\nparticles.particleLifeSpan = 2\nparticles.particleSize = 0.1\nparticles.particleColor = .orange\nparticles.emitterShape = SCNSphere(radius: 0.5)\nparticles.particleVelocity = 2\nparticles.isAffectedByGravity = true\nparticles.blendMode = .additive\n\nlet emitterNode = SCNNode()\nemitterNode.addParticleSystem(particles)\nscene.rootNode.addChildNode(emitterNode)\n```\n\nLoad from Xcode particle editor with\n`SCNParticleSystem(named: \"fire.scnp\", inDirectory: nil)`. Particles can\ncollide with geometry via `colliderNodes`.\n\n## Loading Models\n\nSceneKit loads `.usdz`, `.scn`, `.dae`, `.obj`, and `.abc`. Prefer `.usdz`.\n\n```swift\nguard let scene = SCNScene(named: \"art.scnassets/ship.scn\") else { return }\nlet scene = try SCNScene(url: Bundle.main.url(\n    forResource: \"model\", withExtension: \"usdz\")!)\nguard let modelNode = scene.rootNode.childNode(withName: \"mesh\", recursively: true) else { return }\n```\n\nUse `SCNReferenceNode` with `.onDemand` loading policy for large models.\nUse `SCNSceneSource` to inspect or selectively load entries from a file.\n\n## SwiftUI Integration\n\n`SceneView` embeds SceneKit in SwiftUI:\n\n```swift\nimport SwiftUI\nimport SceneKit\n\nstruct SceneKitView: View {\n    let scene: SCNScene = {\n        let scene = SCNScene()\n        let sphere = SCNNode(geometry: SCNSphere(radius: 1))\n        sphere.geometry?.firstMaterial?.lightingModel = .physicallyBased\n        sphere.geometry?.firstMaterial?.diffuse.contents = UIColor.systemBlue\n        sphere.geometry?.firstMaterial?.metalness.contents = 0.8\n        scene.rootNode.addChildNode(sphere)\n        return scene\n    }()\n\n    var body: some View {\n        SceneView(scene: scene,\n                  options: [.allowsCameraControl, .autoenablesDefaultLighting])\n    }\n}\n```\n\nOptions: `.allowsCameraControl`, `.autoenablesDefaultLighting`,\n`.jitteringEnabled`, `.temporalAntialiasingEnabled`.\n\nFor render loop control, wrap `SCNView` in `UIViewRepresentable` with an\n`SCNSceneRendererDelegate` coordinator. See [references/scenekit-patterns.md](references/scenekit-patterns.md).\n\n## Common Mistakes\n\n### Not adding a camera or lights\n\n```swift\n// DON'T: Scene renders blank or black -- no camera, no lights\nsceneView.scene = scene\n\n// DO: Add camera + lights, or use convenience flags\nlet cameraNode = SCNNode()\ncameraNode.camera = SCNCamera()\ncameraNode.position = SCNVector3(0, 5, 15)\nscene.rootNode.addChildNode(cameraNode)\nsceneView.pointOfView = cameraNode\nsceneView.autoenablesDefaultLighting = true\n```\n\n### Using exact geometry for physics shapes\n\n```swift\n// DON'T\nnode.physicsBody = SCNPhysicsBody(type: .dynamic,\n    shape: SCNPhysicsShape(geometry: complexMesh))\n\n// DO: Simplified primitive\nnode.physicsBody = SCNPhysicsBody(type: .dynamic,\n    shape: SCNPhysicsShape(\n        geometry: SCNBox(width: 1, height: 2, length: 1, chamferRadius: 0),\n        options: nil))\n```\n\n### Modifying transforms on dynamic bodies\n\n```swift\n// DON'T: Resets physics simulation\ndynamicNode.position = SCNVector3(5, 0, 0)\n\n// DO: Use forces/impulses\ndynamicNode.physicsBody?.applyForce(SCNVector3(10, 0, 0), asImpulse: true)\n```\n\n### Exceeding 8 lights per node\n\n```swift\n// DON'T: 20 lights with no attenuation\nfor _ in 0..<20 {\n    let light = SCNNode()\n    light.light = SCNLight()\n    light.light?.type = .omni\n    scene.rootNode.addChildNode(light)\n}\n\n// DO: Set attenuationEndDistance so SceneKit skips distant lights\nlight.light?.attenuationEndDistance = 10\n```\n\n## Review Checklist\n\n- [ ] Scene has at least one camera node set as `pointOfView`\n- [ ] Scene has appropriate lighting (or `autoenablesDefaultLighting` for prototyping)\n- [ ] Physics shapes use simplified geometry, not full mesh detail\n- [ ] `contactTestBitMask` set for bodies that need collision callbacks\n- [ ] `SCNPhysicsContactDelegate` assigned to `scene.physicsWorld.contactDelegate`\n- [ ] Dynamic body transforms changed via forces/impulses, not direct position\n- [ ] Lights limited to 8 per node; `attenuationEndDistance` set on point/spot lights\n- [ ] Materials use `.physicallyBased` lighting model for realistic rendering\n- [ ] 3D assets use `.usdz` format where possible\n- [ ] `SCNReferenceNode` used for large models to enable lazy loading\n- [ ] Particle `birthRate` and `particleLifeSpan` balanced to control particle count\n- [ ] `categoryBitMask` used to scope lights and cameras to relevant nodes\n- [ ] SwiftUI scenes use `SceneView` or `UIViewRepresentable`-wrapped `SCNView`\n- [ ] Deprecation acknowledged; RealityKit evaluated for new projects\n\n## References\n\n- See [references/scenekit-patterns.md](references/scenekit-patterns.md) for custom geometry, shader modifiers,\n  node constraints, morph targets, hit testing, scene serialization, render loop\n  delegates, performance optimization, SpriteKit overlay, LOD, and Metal shaders.\n- [SceneKit documentation](https://sosumi.ai/documentation/scenekit)\n- [SCNScene](https://sosumi.ai/documentation/scenekit/scnscene)\n- [SCNNode](https://sosumi.ai/documentation/scenekit/scnnode)\n- [SCNView](https://sosumi.ai/documentation/scenekit/scnview)\n- [SceneView (SwiftUI)](https://sosumi.ai/documentation/scenekit/sceneview)\n- [SCNGeometry](https://sosumi.ai/documentation/scenekit/scngeometry)\n- [SCNMaterial](https://sosumi.ai/documentation/scenekit/scnmaterial)\n- [SCNLight](https://sosumi.ai/documentation/scenekit/scnlight)\n- [SCNCamera](https://sosumi.ai/documentation/scenekit/scncamera)\n- [SCNAction](https://sosumi.ai/documentation/scenekit/scnaction)\n- [SCNPhysicsBody](https://sosumi.ai/documentation/scenekit/scnphysicsbody)\n- [SCNParticleSystem](https://sosumi.ai/documentation/scenekit/scnparticlesystem)\n- [WWDC 2025 session 288: Bring your SceneKit project to RealityKit](https://sosumi.ai/videos/play/wwdc2025/288/)","tags":["scenekit","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-scenekit","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/scenekit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.684","qualityRationale":"deterministic score 0.68 from registry signals: · indexed on github topic:agent-skills · 468 github stars · SKILL.md body (15,015 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:53:44.446Z","embedding":null,"createdAt":"2026-04-18T22:01:14.824Z","updatedAt":"2026-04-22T00:53:44.446Z","lastSeenAt":"2026-04-22T00:53:44.446Z","tsv":"'-2':640 '-5':323,346 '-9.8':993 '/documentation/scenekit)':1493 '/documentation/scenekit/sceneview)':1510 '/documentation/scenekit/scnaction)':1530 '/documentation/scenekit/scncamera)':1526 '/documentation/scenekit/scngeometry)':1514 '/documentation/scenekit/scnlight)':1522 '/documentation/scenekit/scnmaterial)':1518 '/documentation/scenekit/scnnode)':1501 '/documentation/scenekit/scnparticlesystem)':1538 '/documentation/scenekit/scnphysicsbody)':1534 '/documentation/scenekit/scnscene)':1497 '/documentation/scenekit/scnview)':1505 '/ship.scn':230,1076 '/videos/play/wwdc2025/288/)':1551 '0':305,307,319,327,332,344,595,596,599,621,682,751,753,760,764,806,807,828,830,896,917,919,926,928,935,937,951,992,994,1230,1274,1291,1292,1300,1301,1319 '0.1':698,1018 '0.2':459 '0.3':542,776,910 '0.5':376,503,623,787,792,809,1024 '0.8':454,1158 '1':306,308,544,629,630,634,635,755,766,829,890,894,936,950,956,957,962,1146,1268,1272 '1.0':790,802 '1.2':785 '10':600,601,707,918,1299,1341 '100':1014 '15':684,1232 '2':321,339,340,341,345,632,752,832,834,892,938,963,1016,1026,1270 '2.0':907 '20':567,578,1312,1320 '2025':81,116,1540 '2048':611,613 '288':118,1542 '3':594 '3.0':617 '3d':3,12,35,46,1411 '4':330 '45':333 '5':683,805,927,1231,1290 '500':700 '6.3':58 '60':580,695 '8':615,647,1305,1395 'abc':1065 'accept':491 'acknowledg':1455 'across':86 'ad':1196 'add':39,196,1216 'addit':1030 'albedo':452 'allowscameracontrol':195,1171,1174 'alpha':543,622 'ambient':530,535,538 'ambient.color':539 'ambient.type':537 'anim':27,75,141,142,727,731,740,798,815,817,820,838 'animation.duration':833 'animation.repeatcount':835 'animation.tovalue':824 'ao':470 'app':101 'appear':400 'appl':41,88,111 'appli':23,911 'applyforc':915,924,1297 'applytorqu':933 'approach':732 'appropri':1356 'array':411 'art.scnassets':229,1075 'art.scnassets/ship.scn':228,1074 'asimpuls':920,929,939,1302 'asset':232,238,1412 'assign':1380 'attach':509,581,664,742 'attenu':1316 'attenuationenddist':652,1333,1340,1398 'autoenablesdefaultlight':1172,1175,1359 'avplay':499 'axi':526 'balanc':1431 'base':63,72,440 'bezier':367 'birthrat':1428 'bit':625 'black':192,1208 'blank':1206 'blinn':475 'bloomintens':719 'bloomthreshold':720 'bodi':843,1164,1281,1374,1384 'brick':430,435 'bring':1543 'bug':97 'build':2,18,50 'built':67,198,352 'built-in':66,197,351 'bundl':247 'bundle.main.url':244,1084 'cabasicanim':821 'calay':497 'callback':1378 'camera':139,140,211,293,663,1198,1210,1217,1349,1442 'camera.automaticallyadjustszrange':701 'camera.fieldofview':694 'camera.orthographicscale':706 'camera.usesorthographicprojection':704 'camera.zfar':699 'camera.znear':697 'cameranod':676,689,691,1224,1234,1236 'cameranode.camera':678,1226 'cameranode.look':685 'cameranode.position':680,1228 'catalog':233 'categori':624,631,639 'categorybitmask':965,1436 'cgfloat':494 'cgsize':609 'chamferradius':895,1273 'chang':1386 'checklist':166,169,1343 'childnod':301,313 'childnode.position':303 'code':867 'code-driven':866 'collid':1051 'collidernod':1055 'collis':852,941,1377 'collisionbitmask':968 'color':416,426 'common':160,163,1193 'common-mistak':162 'complexmesh':1255 'compos':739 'cone':570 'cone-shap':569 'configur':692,723 'constant':482 'constraint':1471 'contact':981 'contact.nodea':985 'contact.nodeb':987 'contacttestbitmask':972,1371 'content':122,261 'continu':102,922 'control':212,1181,1433 'conveni':1221 'coordin':276,284,1189 'core':816 'count':1435 'creat':11,215,1001 'critic':96 'custom':210,1466 'dae':1062 'declar':734 'default':476 'defin':267,398,671 'degre':334,696 'deleg':1480 'deprec':78,85,1454 'depth':709 'depth-of-field':708 'deriv':874 'descend':264 'detail':1370 'detect':942 'didbegin':980 'diffus':480 'diffuse-on':479 'diffuse.contents':1153 'direct':518,533,545,550,553,560,590,724,1390 'directional.castsshadow':554 'directional.type':552 'disabl':206 'distant':661,1337 'document':1490 'done':812 'driven':868 'duallay':505 'durat':754,765,775,786,791 'dynam':848,902,1251,1262,1280,1383 'dynamicnode.physicsbody':1296 'dynamicnode.position':1288 'editor':1042 'effect':717,1002 'els':234,1077,1097 'emb':1122 'emitternod':1032,1037 'emitternode.addparticlesystem':1034 'empti':222 'enabl':1424 'enemi':388,394,954 'entri':1115 'evalu':1457 'everi':255 'exact':1240 'exceed':1304 'exist':100,262 'explicit':814 'extrud':366 'fadeout':774 'fals':921,997 'fatalerror':235 'field':711 'file':1118 'find':377 'fire':1004 'fire.scnp':1046 'firstmateri':402,1148,1152,1156 'fix':98 'flag':1222 'float.pi':593,831 'floor.physicsbody':853 'focusdist':713 'follow':519 'forc':851,912 'forces/impulses':1295,1388 'forkey':839 'format':1415 'forresourc':248,1085 'frame':183 'framework':48 'fstop':714 'full':1368 'func':976 'game':736 'game-ori':735 'geometri':69,130,134,254,373,407,877,887,1053,1143,1241,1254,1265,1366,1467 'gestur':204 'graph':65 'graviti':988 'ground':960 'group':768 'guard':223,1069,1089 'guidanc':121 'hand':283 'handlecollis':983 'hasprefix':393 'hdr':716 'height':612,891,1269 'hierarchi':20 'high':44 'high-level':43 'hit':1474 'immov':859 'implicit':797 'import':178,1127,1129 'indirectori':1047 'infin':836 'infinit':778 'inspect':1111 'instant':931 'int':949,955,961 'integr':156,159,1120 'io':55 'isaffectedbygrav':996 'jitteringen':1176 'keypath':822 'kinemat':863 'lambert':478 'larg':1106,1421 'lazi':1425 'least':1347 'length':893,1271 'let':180,219,224,239,295,300,370,380,387,420,444,534,549,561,572,586,675,746,756,780,819,884,947,953,959,1010,1031,1070,1079,1090,1134,1137,1140,1223,1321 'level':45 'light':26,74,137,138,471,508,516,527,558,641,648,655,1200,1212,1218,1306,1313,1322,1330,1338,1357,1392,1402,1406,1440 'light.castsshadow':606 'light.categorybitmask':628 'light.light':1324,1326,1339 'light.shadowcolor':618 'light.shadowmapsize':608 'light.shadowradius':616 'light.shadowsamplecount':614 'lightingmodel':1149 'lightnod':587,603 'lightnode.eulerangles':591 'lightnode.light':589 'lightnode.position':597 'like':1003 'limit':1393 'lit':637 'load':34,150,153,1038,1056,1059,1103,1114,1426 'loading-model':152 'lod':1485 'loop':779,1180,1479 'mainten':94 'major':109 'mask':626 'mass':906 'materi':24,73,135,136,396,406,410,415,421,438,486,1403 'material.diffuse.contents':423,427 'material.isdoublesided':506 'material.normal.contents':432 'material.transparency':502 'material.transparencymode':504 'max':384 'maximum':645 'maxnod':381 'mesh':1094,1369 'metal':1487 'metalness.contents':1157 'metalness/roughness':474 'migrat':120 'miss':236 'mistak':161,164,1194 'mode':95 'model':36,151,154,472,1057,1086,1107,1407,1422 'modelnod':1091 'modifi':1277,1469 'morph':1472 'move':747,769 'multi':414 'multi-materi':413 'name':227,429,434,451,465,469,1045,1073 'need':214,1376 'negat':523 'new':106,1459 'nil':850,858,865,872,898,1048,1276 'node':19,62,128,132,252,265,266,371,378,390,514,521,584,650,662,669,744,1308,1350,1397,1445,1470 'node-bas':61 'node.addanimation':837 'node.categorybitmask':633 'node.eulerangles':324 'node.name':392 'node.opacity':808 'node.physicsbody':845,899,905,908,914,923,932,995,1248,1259 'node.position':316,803 'node.runaction':767,772,793 'node.scale':337 'node.simdposition':342 'nodes-and-geometri':131 'normal':436,466 'notic':79 'nsvalu':825 'obj':1063 'object':741 'offici':84 'omni':556,562,565,1328 'omni.attenuationenddistance':566 'omni.type':564 'ondemand':1102 'one':1348 'optim':1482 'option':897,1170,1173,1275 'orang':1020 'orbit':200 'orient':269,737 'orthograph':703 'overlay':1484 'pan':201 'parallel':546 'parent':274,311 'parentnod':296,299 'parentnode.addchildnode':312 'particl':145,148,998,1011,1035,1041,1049,1427,1434 'particle-system':147 'particlelifespan':1430 'particles.birthrate':1013 'particles.blendmode':1029 'particles.emittershape':1021 'particles.isaffectedbygravity':1027 'particles.particlecolor':1019 'particles.particlelifespan':1015 'particles.particlesize':1017 'particles.particlevelocity':1025 'path':368 'pbr':442,445 'pbr.ambientocclusion.contents':467 'pbr.diffuse.contents':449 'pbr.lightingmodel':447 'pbr.metalness.contents':453 'pbr.normal.contents':463 'pbr.roughness.contents':458 'per':649,1307,1396 'perform':350,879,1481 'phong':477 'physic':31,71,77,143,144,439,841,842,1243,1286,1362 'physicallybas':448,473,1150,1405 'physicscategori':945 'physicscategory.enemy':970,973 'physicscategory.ground':969 'physicscategory.player':966 'physicsworld':977 'pi':329,762 'platform':89 'platform.physicsbody':860 'player':948 'playernode.physicsbody':964,967,971 'point':557 'point/spot':654,1401 'pointofview':1353 'polici':1104 'posit':268,1391 'possibl':1417 'prefer':347,1066 'primit':70,354,1258 'print':811 'product':208 'project':107,1460,1546 'properti':487 'prototyp':1361 'provid':59,729 'puls':781,795 'radius':375,1023,1145 'rain':1006 'ray':547 'realist':1409 'realitykit':113,1456,1548 'recommend':112 'recurs':385,1095 'refer':170,171,1461 'references/scenekit-patterns.md':1191,1192,1463,1464 'relev':1444 'removefromparentnod':777 'render':47,441,643,1179,1205,1410,1478 'repeatforev':794 'reset':1285 'restitut':909 'return':1078,1098,1161 'reusabl':738 'review':165,168,1342 'review-checklist':167 'right':282,287 'right-hand':281 'rootnod':259 'rotat':336,757,770,823 'scalar':455,460,495 'scale':271,783,788 'scene':4,51,64,123,126,172,220,225,237,240,256,1071,1080,1135,1138,1162,1168,1169,1204,1214,1344,1354,1447,1476 'scene-setup':125 'scene.physicsworld.contactdelegate':974,1382 'scene.physicsworld.gravity':990 'scene.rootnode.addchildnode':298,602,688,1036,1159,1233,1329 'scene.rootnode.childnode':382,1092 'scene.rootnode.childnodes':389 'scenekit':1,8,40,82,179,278,642,657,728,873,1058,1123,1130,1335,1489,1545 'scenekitview':1132 'sceneview':181,194,1121,1167,1449,1506 'sceneview.allowscameracontrol':187 'sceneview.autoenablesdefaultlighting':189,1237 'sceneview.backgroundcolor':191 'sceneview.pointofview':690,1235 'sceneview.scene':185,1213 'scn':38,231,1061 'scnaction':29,733,1527 'scnaction.move':748 'scnaction.rotateby':758 'scnaction.sequence':782 'scnbox':355,888,1266 'scncamera':666,679,726,1227,1523 'scncapsul':360 'scncone':358 'scncylind':357 'scnfloor':363 'scngeometri':1511 'scnlight':511,536,551,563,574,1325,1519 'scnmateri':397,422,446,1515 'scnmaterialproperti':490 'scnnode':22,297,302,372,588,677,1033,1142,1225,1323,1498 'scnparticlesystem':1000,1012,1044,1535 'scnphysicsbodi':33,846,854,861,900,1249,1260,1531 'scnphysicscontact':982 'scnphysicscontactdeleg':1379 'scnphysicsshap':886,1253,1264 'scnphysicsworld':979 'scnplane':362 'scnreferencenod':1100,1418 'scnscene':17,186,217,221,226,242,1072,1082,1136,1139,1494 'scnscenerendererdeleg':1188 'scnscenesourc':1109 'scnshape':365 'scnsphere':356,374,1022,1144 'scntext':364 'scntorus':359 'scntransact':796 'scntransaction.animationduration':801 'scntransaction.begin':800 'scntransaction.commit':813 'scntransaction.completionblock':810 'scntube':361 'scnvector3':304,317,325,338,592,598,681,750,804,916,925,991,1229,1289,1298 'scnvector3zero':687 'scnvector4':826,827,934 'scnview':15,174,182,1183,1453,1502 'scope':1439 'screenspaceambientocclusionintens':721 'see':114,1190,1462 'select':1113 'self':975 'sequenc':773 'sequenti':771 'serial':1477 'session':117,1541 'set':1332,1351,1372,1399 'setup':124,127,173 'shader':1468,1488 'shadow':604 'shadowon':484 'shape':571,849,857,864,870,882,885,903,904,1244,1252,1263,1363 'simd':348 'simd3':343 'simplifi':881,1257,1365 'simul':30,1287 'singl':405 'single-materi':404 'skill' 'skill-scenekit' 'skip':658,1336 'sktextur':496 'smoke':1005 'solid':425 'sosumi.ai':1492,1496,1500,1504,1509,1513,1517,1521,1525,1529,1533,1537,1550 'sosumi.ai/documentation/scenekit)':1491 'sosumi.ai/documentation/scenekit/sceneview)':1508 'sosumi.ai/documentation/scenekit/scnaction)':1528 'sosumi.ai/documentation/scenekit/scncamera)':1524 'sosumi.ai/documentation/scenekit/scngeometry)':1512 'sosumi.ai/documentation/scenekit/scnlight)':1520 'sosumi.ai/documentation/scenekit/scnmaterial)':1516 'sosumi.ai/documentation/scenekit/scnnode)':1499 'sosumi.ai/documentation/scenekit/scnparticlesystem)':1536 'sosumi.ai/documentation/scenekit/scnphysicsbody)':1532 'sosumi.ai/documentation/scenekit/scnscene)':1495 'sosumi.ai/documentation/scenekit/scnview)':1503 'sosumi.ai/videos/play/wwdc2025/288/)':1549 'source-dpearson2699' 'spaceship':249 'spark':1008 'sphere':1141,1160 'sphere.firstmaterial':437 'sphere.geometry':1147,1151,1155 'spin':840 'spot':568,573,576 'spot.spotinnerangle':577 'spot.spotouterangle':579 'spot.type':575 'spritekit':1483 'static':856,946,952,958 'struct':944,1131 'sunlight':548 'surfac':399 'swift':57,177,218,294,315,369,379,419,443,501,529,585,605,627,674,693,745,799,818,844,883,913,943,989,1009,1068,1126,1201,1245,1282,1309 'swiftui':155,158,1119,1125,1128,1446,1507 'swiftui-integr':157 'system':146,149,277,285,999 'target':1473 'temporalantialiasingen':1177 'test':1475 'textur':418,431,457,462 'three':730 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'toward':291 'transform':314,1278,1385 'transpar':500 'tri':241,1081 'true':188,190,386,395,507,555,607,702,705,930,940,1028,1096,1238,1303 'type':528,847,855,862,901,1250,1261,1327 'typic':205 'uicolor':492,540,619 'uicolor.systemblue':424,1154 'uiimag':428,433,450,464,468,493 'uikit':176 'uiviewrepresent':1185,1451 'uniform':531 'unit':309 'unlit':483 'updat':110 'url':243,1083 'usdz':37,245,251,1060,1067,1088,1414 'use':7,9,56,279,401,651,880,1099,1108,1220,1239,1294,1364,1404,1413,1419,1437,1448 'var':1163 'via':1054,1387 'view':13,1133,1166 'view.addsubview':193 'view.bounds':184 'viewpoint':673 'visual':6,53 'wantsdepthoffield':712 'wantshdr':718 'white':541,620 'width':610,889,1267 'withextens':250,1087 'withnam':383,1093 'work':104 'world':978 'wrap':1182,1452 'wwdc':80,115,1539 'x':286,318,326,759 'xcode':1040 'y':288,320,328,335,761 'z':290,322,331,525,763 'z-axi':524 'zoom':203","prices":[{"id":"b370777c-7b09-4395-9753-61e140cf5ce6","listingId":"6d4d612d-2aab-4080-a6d4-dd23ee820a13","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:01:14.824Z"}],"sources":[{"listingId":"6d4d612d-2aab-4080-a6d4-dd23ee820a13","source":"github","sourceId":"dpearson2699/swift-ios-skills/scenekit","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/scenekit","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:14.824Z","lastSeenAt":"2026-04-22T00:53:44.446Z"}],"details":{"listingId":"6d4d612d-2aab-4080-a6d4-dd23ee820a13","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"scenekit","github":{"repo":"dpearson2699/swift-ios-skills","stars":468,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-21T19:26:16Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"a43998736b55fdd6a8f932722f55dd47b4992395","skill_md_path":"skills/scenekit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/scenekit"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"scenekit","description":"Build 3D scenes and visualizations using SceneKit. Use when creating 3D views with SCNView and SCNScene, building node hierarchies with SCNNode, applying materials and lighting, animating with SCNAction, simulating physics with SCNPhysicsBody, loading 3D models (.usdz, .scn), adding particle effects, or embedding SceneKit in SwiftUI with SceneView. Note: SceneKit was deprecated at WWDC 2025 and is in maintenance mode; RealityKit is recommended for new projects."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/scenekit"},"updatedAt":"2026-04-22T00:53:44.446Z"}}