SceneKit Tutorial With Swift Part 2: Nodes

In the second installment of our SceneKit With Swift tutorial, you’ll dive into coding your first 3D iOS game, Geometry Fighter, by learning about nodes. By Chris Language.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

Adding a Geometry Node

Your next task is to create a method that spawns the various random shapes defined in ShapeType.

Add the following method to GameViewController.swift, right below setupCamera():

func spawnShape() {
  // 1
  var geometry:SCNGeometry
  // 2
  switch ShapeType.random() {
  default:
    // 3
    geometry = SCNBox(width: 1.0, height: 1.0, length: 1.0,
      chamferRadius: 0.0)
  }  
  // 4
  let geometryNode = SCNNode(geometry: geometry)
  // 5
  scnScene.rootNode.addChildNode(geometryNode)
}

Taking each numbered comment in turn:

  1. First, you create a placeholder geometry variable for use a bit later on.
  2. Next, you define a switch statement to handle the returned shape from ShapeType.random(). It’s incomplete at the moment, and only creates a box shape; you’ll add more to it in the challenge at the end of this tutorial.
  3. Then, you create an SCNBox object and store it in geometry. You specify the width, height and length, along with the chamfer radius (which is a fancy way of saying rounded corners).
  4. Here, you create an instance of SCNNode named geometryNode. This time, you make use of the SCNNode initializer which takes a geometry parameter to create a node and automatically attach the supplied geometry.
  5. Finally, you add the node as a child of the scene’s root node.

Now you need to call this method. Add the following line to viewDidLoad() below setupCamera():

spawnShape()

Build and run; you’ll see a white square displayed onscreen:

BuildAndRun2

There are a few things to observe here:

  • The box node is the default shape from spawnShape(), and it sits at (x:0, y:0, z:0) in the scene.
  • You’re viewing the scene through your cameraNode. Since the camera node lives at (x:0, y:0: z:10), the box is smack dab in the center of the camera’s viewable area.

OK, it’s not very exciting, and it’s hardly three-dimensional — but fear not… the next section changes all of that!

Built-in View Features

SCNView comes with a few out-of-the-box features to help make your life easier.

Add the following lines to setupView() in GameViewController.swift, just below the current implementation:

// 1
scnView.showsStatistics = true
// 2
scnView.allowsCameraControl = true
// 3
scnView.autoenablesDefaultLighting = true

Here’s an explanation of the code above:

  1. showStatistics enables a real-time statistics panel at the bottom of your scene.
  2. allowsCameraControl lets you manually control the active camera through simple gestures.
  3. autoenablesDefaultLighting creates a generic omnidirectional light in your scene so you don’t have to worry about adding your own light sources.

Build and run; things should look a little more exciting this time around!

BuildAndRun3

You can use the following gestures to control the active camera in your scene:

  • Single finger swipe: Rotates your active camera around the contents of the scene.
  • Two finger swipe: Moves, or pans your camera left, right, up or down in the scene.
  • Two finger pinch: Zooms the camera in and out of the scene.
  • Double-tap: If you have more than one camera, this switches between the cameras in your scene. Of course, since you have only one camera in the scene, this doesn’t do that. However, it also has the effect of resetting the camera to its original position and settings.

Working with Scene Statistics

Find the statistics panel at the bottom of the screen:

Statistics0

Here’s a quick breakdown of what each element means:

  • fps: Stands for frames per second. This a measurement of the total amount of consecutive frame redraws done in one-second. The lower this amount, the more poorly your game is performing. You typically want your game to run at 60fps, which will make your game look and feel smooth.
  • : Stands for total draw calls per frame. This is typically the total amount of visible objects drawn per single frame. Lights affecting objects can also increase the amount of draw calls of an object. The lower this amount, the better.
  • : Stands for total polygons per frame. This the total amount of polygons used to draw a single frame for all the visible geometry. The lower this amount, the better.
  • : Stands for total visible light sources. This is the total amount of light sources currently affecting visible objects. The SceneKit guidelines recommend not using more than 3 light sources at a time.

Click on the + button to expand the panel and reveal more detail:

Statistics1

This panel provides you with the following information:

  • Frame time: This is the total amount of time it took to draw a single frame. A frame time of 16.7ms is required to achieve a frame rate of 60fps.
  • The color chart: This provides you with a rough frame time percentage breakdown per component within the SceneKit rendering pipeline.

From this example, you now know that it took 22.3ms to draw a single frame of which ±75% was used for Rendering, and ±25% was used for GL Flush.

Note: The SceneKit rendering pipeline will be discussed in more detail later on.

You can click the button to minimize the panel again.

Isn’t it great that all these features are built-in? :]

Challenges

It’s important for you to practice what you’ve learned, on your own, so many parts of this series have one or more challenges associated with them.

I highly recommend trying all of the challenges. While following a step-by-step tutorial is educational, you’ll learn a lot more by solving a problem by yourself.

If you get stuck, you can find solutions in the resources for the tutorial — but to get the most from this series, give it your best shot before you look!

Your First Challenge

There’s only one challenge in this tutorial, but it’s a fun one.

Your challenge is to improve the switch statement inside spawnShape() to handle the remaining shapes in the enumerator.

Use Apple’s official SceneKit documentation (http://apple.co/2aDBgtH) as a guide to the various geometric shapes. Also, take a look at the ShapeType enum to see which shapes are left to create; their names should give you a good idea of where to start.

Don’t worry too much about the sizes to use; just try to make them about the same relative size as the box you made earlier.

After this challenge, you’ll have a firm grasp on some of the most fundamental concepts in SceneKit! :]