Build 2D games and animations using SpriteKit. Use when creating game scenes with SKScene and SKView, adding sprites with SKSpriteNode, animating with SKAction sequences, simulating physics with SKPhysicsBody and contact detection, creating particle effects with SKEmitterNode, building tile maps, using SKCameraNode, or integrating SpriteKit scenes in SwiftUI with SpriteView.
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Build 2D games and interactive animations for iOS 26+ using SpriteKit and Swift 6.3. Covers scene lifecycle, node hierarchy, actions, physics, particles, camera, touch handling, and SwiftUI integration.
SKScene identity stable when hosted by SpriteView.// DON'T: Scene is recreated on every body evaluation
var body: some View {
SpriteView(scene: GameScene(size: CGSize(width: 390, height: 844)))
}
// DO: Create once and reuse
@State private var scene = GameScene(size: CGSize(width: 390, height: 844))
var body: some View {
SpriteView(scene: scene)
}A node can only have one parent. Remove from the current parent first or create a separate instance. Adding a node that already has a parent crashes.
// DON'T: Bodies collide but didBegin is never called
player.physicsBody?.categoryBitMask = PhysicsCategory.player
enemy.physicsBody?.categoryBitMask = PhysicsCategory.enemy
// DO: Set contactTestBitMask to receive contact callbacks
player.physicsBody?.contactTestBitMask = PhysicsCategory.enemySKShapeNode uses a separate draw call per instance. Prefer SKSpriteNode
with a texture for repeated elements to enable batched rendering.
// DON'T
enemy.run(SKAction.moveBy(x: -800, y: 0, duration: 3.0))
addChild(enemy)
// DO: Remove after leaving the visible area
enemy.run(SKAction.sequence([
SKAction.moveBy(x: -800, y: 0, duration: 3.0),
SKAction.removeFromParent()
]))
addChild(enemy)Set physicsWorld.contactDelegate = self in didMove(to:), not in
update(_:) or after a delay.
didMove(to:) for setup, not initscaleMode chosen appropriately for the game's designignoresSiblingOrder set to true on SKView for performancezPosition used consistently when ignoresSiblingOrder is enabledcontactDelegate set in didMove(to:)contactTestBitMask set for any pair needing didBegin/didEnd callbacksisDynamic = falseSKShapeNode avoided in performance-critical paths; SKSpriteNode preferred.removeFromParent() in sequencetargetNode set when particles should stay in world space@State when used with SpriteView in SwiftUIupdate(_:) uses delta time for frame-rate-independent movementthienqo/ios-skills
6bf8b62
Canonical home
since May 23, 2026
Also appears in
on Sep 6, 2026
since May 22, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.