Building a Game with SceneKit

WWDC2014: Building a Game with SceneKit

Managing Assets

// Load two scenes
SCNScene *mainScene = [SCNScene sceneNmaed:@"level.dae"];
SCNScene *characterScene = [SCNScene sceneNamed:@"monkey.dae"];

// Get the monkey
SCNNode *monkey = [characterScene.rootNode childNodeWithName:@"monkey" recursively:YES];

// Add a monkey to the level
[mainScene.rootNode addChildNode:monkey];

// Add another monkey to the level
[mainScene.rootNode addChildeNode:[monkey clone]];

Behaviors

Animating characters

  • skinned-character.da
  • run.dae
  • jump.dae
  • idle.dae
// Load an animation
CAAnimation *anim = [sceneSource entryWithIdentifier:animationName withClass:[CAAnimation class]];

// Play it
[character addAnimation:anim forKey:@"run"];

Moving characters

Collision Detection

// Be notified through delegation
- (void)physicsWorld:(SCNPhysicsWorld *)world
     didBeginContact:(SCNPhysicsContact *)contact;

// Or explicitly perform ray tests
- (NSArray *)rayTestWithSegmentFromPoint:(SCNVector3)origin
                                 toPoint:(SCNVector3)dest
                                 options:(NSDictionary *)options;

// Animating items
[aBanana runAction:
  [SCNAction repeatActionForever:
    [SCNAction rotateByX:0.0 y:2.0 * M_PI z:0.0 duration:2.0]]];

Particles

// Load a particle system
SCNParticleSystem *particleSystem =
  [SCNParticleSystem particleSystemNamed:@"dust.scnp"
                             inDirectory:@"art.scnassets/particles"];

// Attach to a node
[character addparticleSystem:particleSystem];

// Control emission
particleSystem.birthRate = shouldEmit ? aBirthRate : 0;

Visual Improvements

NSString *modifier = @"_geometry.texcoords[0] +=
vec2(
    sin(_geometry.position.z + u_time) * 0.01,
    -0.05 * u_time
);";

lavaNode.geometry.shaderModifiers =
  @{SCNShaderModifierEntryPointGeometry : modifier};

Postprocessing

  • UIWindow
    • SCNView -SKScene(SpriteKey overlays)
      • Score
      • Timer
      • title screen

Performance Optimization

CPU 瓶頸,通常是 draw calls 過多造成。

Flattening,降低 draw calls 次數

  • Flatten directly in 3D tools(recommended)
  • Flatten programmatically
SCNNode *flattenedNode = [node flattenedClone];

GPU 瓶頸

  • Fill Rate limited(要求 GPU render 過多 pixels)
    • 降低 contents scale factor(1x, 2x),縮小圖檔尺寸 512x512->256x256
    • Reduce screen space postprocesses(shadows,depth of field,reflective floor)
  • Fragment shaders limited
    • 儘可能使用 Static Lighting
    • 設置適當 Omni Light
    • Dynamic shadow 可以用 Projected shadow 代替
    • texture size
    • mipmapping(缺點:載入的時間長,會花比較多的記憶體~30%)

Summary: Performance

  • CPU
    • Reduce draw calls by flattening
    • Less physic bodies
    • Less animations
    • Less actions
  • Tiler
    • Levels of detail
    • Split scenes in chunks
  • Renderer or device
    • Simpler materials
    • Less/Simpler lights
    • Smaller textures, mipmapping
    • Downscaled contents size
    • Less postprocess
    • No multisampling