We wanted to make scale a first class citizen in ARFoundation, so I’d like to clarify how it works. A basic AR scene has an ARSession and an ARSessionOrigin. The job of the ARSessionOrigin is to transform “session space” (the coordinate system used by the device) into “world space” (a position, rotation, and scale in Unity). The AR camera should be a child of the ARSessionOrigin, so if you want your AR camera to start at a non trivial position in the Unity scene, simply move the session origin to that position. That seems straightforward enough.
However, you might find scale harder to get your head around. What are we scaling anyway? What does that mean? If I have a single Unity cube in my scene, and I set the scale to something other than (1, 1, 1), what should I expect to happen?
WTF? Why is my cube moving all over the place? Why isn’t it scaling?
The cube is changing apparent size, but also changing apparent position. Imagine if I had two cubes, what would you expect to happen? If both cubes got bigger without moving, then they would overlap. Clearly, they also have to appear to move.
I say “appear” because we aren’t actually scaling the cube; we’re scaling session origin. This means scaling the camera’s position and also all the trackables, such as planes. The blue plane in the GIF above doesn’t appear to move because it and the camera are being scaled together. The end result is that it looks like the entire scene has scaled, when in fact, the session origin (camera + planes) have been scaled by the opposite amount.
Looking instead at the scene view, we see what’s actually happening: the cube doesn’t move at all.
We’re trying to scale the apparent size of the entire scene, so everything will appear to get bigger or smaller and move away from or toward some origin. In fact, the session origin.
So what should you do? Put the session origin at the “middle” of whatever scene you’re trying to scale, and add another GameObject in the hierarchy (between ARSessionOrigin and Camera) to add an additional positional offset to the camera. Wouldn’t it be nice if there were a convenience method to achieve this? In fact, there is!
ARSessionOrigin.MakeContentAppearAt does exactly this. It doesn’t move the content; instead it moves the ARSessionOrigin such that the content you specify appears to be the the position you’ve specified. Example: instead of moving the entire scene 3 meters to the left, move the ARSessionOrigin 3 meters to the right.
Effectively, this puts the ARSessionOrigin at the “center” of the scene, and then also moves the camera by the opposite amount. The effect is that the origin for which all scaling is done is now well defined and controllable.
Here, I’ve created a GameObject in the center of this complex scene, and asked the ARSessionOrigin to MakeContentAppearAt some point I selected on the plane. On the right, we have the GameView, what you would see on your device. It looks like the scene is moving while the plane remains still. However, the scene view on the left reveals that we’re actually moving the session origin around.
Using this method, scaling the session origin finally does what we want:
The content is “scaled” around a point I’ve specified.
And it works for rotation too:
Note how the camera effectively orbits the scene, making it look like the content is rotating.
So why go through all this headache in the first place? Why not just scale the scene and leave the session origin alone? For simple content, like a cube, it’s probably much easier just to scale the content. But for complex scenes, like this village, it might be very expensive, or even impossible. Particle effects cannot be trivially scaled. Scaling physics or nav meshes down to be very tiny is a bad idea – things will start falling through the world, and nav meshes will be too small to work properly. Terrain is static at runtime, and cannot be moved, rotated, or scaled. For these reasons, it’s much more effective to scale the camera + trackables, not the scene content.
Hope that helps clear up some confusion. I’ll look for your questions and feedback below!
-Tim