Creating an Immersive AR Experience. ARTris — Part #2

Grace Elina
Artris Code
Published in
4 min readJan 30, 2018

This article is part #2 of a series of articles on ARTris. A multiplayer real-time 3D AR Tetris game built with ARKit, Node.js, and Firebase. If you’re new to this series, we recommend you begin with the introduction. Fork the iOS Client and the Game Engine repos to start experimenting.

Today we want to talk about how we reduced the number of player interactions with the screen and how we transitioned between two view controllers without interrupting the AR experience.

transitioning to a new view

Reducing gestures

In our first implementation, we used three gestures; pan, pinch, and rotation to align the players’ game coordinate systems. We used the pan-gesture to move the grid around the environment, the pinch-gesture for scaling and the rotation-gesture to rotate it around the y-axis. Using three gestures did not work as well as we hoped. Apple talks about this pitfall in their docs.

For an object with a finite size relative to the real world, like a piece of furniture, scaling is irrelevant if the item is placed at an accurate size. Scaling isn’t a remedy for adjusting the distance of an object — making an object larger to make it appear closer, for example, just results in a larger object that’s still far away.

A two-finger pinch gesture, for example, is quite similar to a two-finger rotation gesture. If you implement two similar gestures like this, be sure to test your app and make sure they’re interpreted properly.

We had the same problems that the Apple docs describe. Using two two-finger gestures became too ambiguous, and the virtual grid did not respond well to them. Also, because players touched the screen too much, the AR immersion broke. So we decided to scale the three touch events down to a single rotation-gesture to minimize the number of user interactions with the screen.

Transitioning between two view controllers

The second roadblock we faced was how to switch from localization to the game-play environment. We came up with two solutions — to use a segue or add a child view controller to the main view controller.

Using a segue

We tried using a segue to transition between two view controllers. The first view controller handles the localization of the grid with the rotation gesture view, and the second handles the game engine and user interactions with the Tetris grid.

First, before segueing we pause the AR session and pass the session to the new view controller. Second, we pass the shadowBinder which is the node unto which the grid is attached. We do this to maintain a pointer to where we had placed the grid.

segue to transition to new view controller

Third, after the transition takes place, in the new view controller, we resume the session with the same configuration as before.

setting the sceneView properties in the game view controller

We had two issues with this kind of transition. First, pausing the AR session disrupts it, and there is no guarantee that it would resume exactly like it was before. Second, for about three seconds the screen turns white while the transition is occurring. Our next attempt was to use a child view controller which gave much better results.

Using a child view controller

A child view controller is essentially a container view controller, but it is managed by a its own view controller class. This gives us a chance to keep our code modular while making sure the AR session is not interrupted.

Before the child view controller is added, the current view controller’s ARSession delegate is set to nil. This is to stop calling its didUpdatFrame function which updates the grid’s position with each rendered frame. This fixes the position of the grid so that the user can start playing the game.

transition using a child view controller

Next, the updateView function is called. This function adds the new view controller as child view controller. Adding a child view controller is done in three steps adding the child view controller to its parent, adding its view as a subview to its parent’s view and updating its view’s bounds.

updateView function

Finally, we need to learn how to instantiate the child view controller. We do this in a lazy declaration and add any references we would want to pass to it from its parent in the initialization closure.

instantiate gameViewController

Now, we’re done! We have successfully managed a transition to a new view controller class without interrupting the AR session.

Next

Tomorrow we will talk about the steps that happen between a touch event and before a new frame gets rendered.
From Touch Events to a New Frame

References and Further Reading

View Controller Programming Guide for iOS

Container View Controllers

Managing View Controllers With Container View Controllers

--

--