Having received a Samsung Galaxy S8 for my birthday (a gift from my wonderful wife), I’ve been playing around a bit with Google’s ARCore preview 2. The most recent creation o’ mine is a 7 hole mini-golf/putt putt game and I thought I’d jot down a few of the trials and tribulations I’ve come across in developing augmented reality games that may help others (or at least my future self).
Scaling for augmented reality is a challenge. In my case I didn’t want to create life sized putt putt tracks, but something that was visually about the size of a coffee table or so. Something you could place on the floor in front of you and walk around if necessary. In order accomplish this, I had to change the import scale of my models (which, incidentally, I got from the Unity Asset Store here, if interested) from 1.0 to .0003. This means, in terms of 3D world space scaling we’re talking about models in the size of millimeters rather than meters. Visually, this will look good on the device but can lead to other problems such as…
One of the first things I noticed when scaling items so small is that two colliders, even perfectly aligned, would send a rolling ball soaring into the air when it crossed the seams. To overcome this massive annoyance, in the Unity3D PhysicsManager, I set the Default Contact Offset to 0.0001. According to the Unity3D docs, “Contact offset allows the collision detection system to predictively enforce the contact constraint even when the objects are slightly separated.” The docs also warn that setting this value too close to 0 can cause jitter, but, again, with such small scaled models, this was not an issue and it worked out fine.
While related to physics, gravity is an entirely separate gotchya item to watch out for when developing for augmented reality. AR is not yet an exact science and you’ll find that occasionally your anchored models will twitch or jump or shift or drift a bit. If you happen to be using the default physics engine gravity when that happens, things will roll, topple, collapse, or otherwise behave like a sudden earthquake just occurred. To get around this, gravity should be turned off on the RigidBodies and a custom gravity applied. In this particular case, each putt putt hole is parented to an empty GameObject. I then used the negative up vector of that item’s Transform to apply a constant force to the golf ball during the FixedUpdate() event. It took a bit mucking about between PhysicMaterials properties, angular drag on the golf ball RigidBody and the gravity force, but I finally settled on: -9.8f / 5f * this.container.up. Doing this means gravity remains constant in the game and won’t be disrupted by AR glitches. It could even be played on the side of a wall in theory (ARCore doesn’t support vertical surface detection out of the box, but you get the picture).
When dealing with models in the scale of millimeters in Unity3D, realtime shadows tend to look horrible. To be honest, I haven’t found a suitable solution to this yet (if anyone has some tips, post them in a comment), but here’s a few things I’ve done. When possible, fake a shadow with a textured quad or a projector/blob shadow. I did that with the golf ball and it looks quite nice. If a real time shadow is best, in the Unity3D Quality Settings, set the shadow distance to somewhere between 50-100 and in the light settings (I’m using a directional light pointing straight down), set the shadow properties to something like: strength very low (around .075 to .1), bias around .05, normal bias around .4, and near plane around .2. Again, the results aren’t great, but they’re passable.
This isn’t AR specific, but a quick tip. In this golf game I have a ‘pointer’ object on the golf ball that will show the direction and strength of a hit when aiming the golf swing. I wanted this object to be visible even if the golf ball is behind a hill or stuck in a windmill or tube or something. The easiest way to do that is use a material that shows above everything else. That is very quick and easy to do in Unity3D just by creating a new Standard Surface Shader. In the tags, add “Queue”=”Overlay” and set ZTest Always. Use this shader in a material that will be applied to whatever you want to appear on top of everything else, and done.
Finally, here’s a little look at the game in action:
If anyone happens to be in the Dublin area and would like to have some fun, I’ll be demoing the live app at the 3DCamp Meetup on February 15. That meetup should be really good. I’m especially looking forward to the Warducks presentation and checking out the other demos. Come on along.