Dealing with Scale

The first item on the to-do list for Rascals was "Create physics environment with scaling transition."  Sounds easy, right?  All we need is an environment where things can be picked up, dropped or thrown in a way that seems natural enough to comply with the physicality requirements, and which can be scaled by a factor of 20.  The physicality side of things is a story of its own, and may be the subject of a future post.  Suffice it to say that for moving the pieces alone, we have scrapped five or six drafts before we finally found the feel we are looking for combined with sufficient precision and consistency.

The scaling transition is a different story altogether, though.  I had assumed that we would simply re-address the play space and change the distance between the VR cameras to create the desired effect, but that was not to be. The first thing Lars did when he sat down to develop, was to create two separate environments in Unity, one in board view scale, and one in first person scale.  He explained the reasoning behind this as "if you want to make the player tiny, then create a world in which he is tiny, don't go scaling the world, that just creates lots of problems".  This may sound perfectly reasonable to a seasoned developer, but I was intensely skeptical from the get-go.  Making the two environments match up did indeed create game breaking issues practically every time we made a major change to anything, and was intensely disruptive to early concept testing.  One of the points Lars made was that you may be able to scale the world if you try hard enough, but you can't just scale physics, but that seemed easier to me than dealing with the mismatch between our two environments.

I finally asked Reddit for help, and this established two things:  First, it is very easy to scale the world in VR;  You simply scale the camera rig in Unity, and there you go.  Second, the trouble is all about scaling physics.  As Lars had pointed out, speed appears very different when you're small.  I thought that this would resolve itself by making small scale movements slower, but I hadn't accounted for the acceleration due to gravity.  If you scale the world my twenty times, gravity also appears twenty times greater than normal, and for a game that relies as heavily on physics as Rascals, this doesn't work at all.  For example, precision throwing is key to using several weapons effectively, but in 20x gravity objects you throw accelerate downwards at such a rate that they appear to snap to the ground.  In short, these problems were not mere details, and the solutions proved non-trivial as well.  We might have gotten away with manipulating the gravity constant (except for the fun we'd have with syncing online multiplayer instances), if it hadn't been for the way we have stacked joints on joints to build the little rascals.  If you have the faintest idea how joints on joints work in Unity, you can easily imagine the ugly, ugly mess you get into when trying to hack micro gravity.

Once we fully understood that this is purely a physics scaling problem, it also became clear that the real challenge is to determine when to run the physics in full scale and when to invoke micro physics.  With this in mind, we decided to stick with the two separate environments.  Not only does this avoid a pretty serious re-write, it also retains some performance benefits of the original model.  To make it all come together, we either stream positional data from the large environment to the small one or vice versa, ensuring that physics only runs in one place and thus avoiding the danger of de-sync.  This makes it easier to run client side physics in network multiplayer, and allows us to concentrate on determining if we need large or small scale physics, which is the real issue anyway.