Today I realized that I’d totally busted shadow behavior in Unity with one of my Orthographic Camera Tips, relating to some very interesting and unexpected behavior in Unity’s Stable Fit shadow mode (the default shadowing mode in a built-in render pipeline). I updated the entry accordingly. The quick jist is to use Close Fit shadows for Isometric gameplay projects because Stable Fit depends on a concept of camera depth that doesn’t exist in orthographic projections.
If you have Stable Fit enabled then this is the kind of behavior you’ll observe when changing the near plane of your orthographic camera. Pay close attention to the shadows under the sphere and along the wall edges
Edit -> Project Settings -> Close Fit – for the Orthographic Win!
During the process of accomplishing some modest goals in isometric gameplay, I’ve taken notes on mistakes and oversights I made while rigging my first orthographic cameras.
(shameless SEO paragraph) The orthographic camera is a staple of Isometric Gameplay Environment, such as both realtime (RTS) and especially turn based (TBS) strategy games. In this entry, I will explain how I implemented a flexible solution to controlling the camera, within the context of the Unity3D 2019 engine. (/end SEO)
Tip #1: Use X/Z coordinates for landscaping
The classic view of an isometric map has X and Y axis for the map surface, and Z as the Up Vector. This has a long history in isometrics being used primarily to depict 2D landscapes, and 2D coordinate systems naturally use X/Y mnemonics. Contrast this with most 3D engines, and Unity specifically, which treat the X and Z vectors as map surface, and the Y as the Up Vector.
Why does it matter? Because the majority of GameObjects, models, and Unity components (most notably the Physics components) default to the assumption that the Up Vector is the Y vector. More importantly, Unity has provided named constants for the Cardinal Vectors for us — Right (x), Up (Y), Forward (Z) — and if we re-orient the entire world to suit a paradigm where Z=Up, those named constants become confusing/misleading. We can remap the Physics Up Vector (aka gravity), and we can re-orient models at runtime using extra transforms (less efficient but not a show-stopper), but we cannot redefine Unity’s built in constants for Vector3.Up, Vector3.Right, and Vector3.Forward.
For this reason I strongly suggest orienting your world map structure such that XZ are the landscape coordinates and Y is UP. This will save you a ton of headaches later on. It’s fine to have XY data in your map assets, but do convert it to XZ data so that you can operate on it using the named constant vectors, and orient your models in an expected way.
Tip #2: Disable the Near Plane Clipping
Size and Clipping Planes define the Orthographic Frustum. For best results, the Near Plane should be set to a very large negative number.
Go ahead and set that Near Clipping Plane to -1000 (usually default value is 0.1 or something), or -100000. If you don’t do this, your camera’s just going to be a total pain to work with and it’s going to trick you into doing some bad things to try and work around seemingly nonsense object clipping behavior.
The technical rationale: The visible area of the screen (camera plane) is determined according to the size parameter, and that combined with the Near/Far clipping planes determine the frustum. The way the frustum works is pretty similar to perspective cameras, meaning that objects are drawn or clipped according to depth — which is a problem because Orthographic views do not have a valid concept of depth.
The only truly valid clipping for an orthographic view is defined by the rectangle of the screen on which the image is being projected. This clipping area is defined by the Sizeparameter alone. If an object, orthographically projected, lives within that space, it should be drawn. If it lives outside that space, it should be clipped. This is the intended operation of an orthographic projection.
Therefore, I personally disable both near and far clipping planes (eg, set them very large, eg -100000) though there could be some advantage for setting the far clipping plane to something lower, if you happen to be implementing an oblique orthographic view where the camera is set low on the horizon. Maybe. It’s a hard sell.
Tip #3: Turn off Stable Fit Shadow Projection
(I have only verified this option using the classic Built-In Render Pipeline – behavior for Universal Render Pipeline surely differs)
Edit -> Project Settings -> Close Fit – for the Orthographic Win!
If you have Stable Fit enabled then this is the kind of behavior you’ll observe when changing the near plane of your orthographic camera. Pay close attention to the shadows under the sphere and along the wall edges
Personally, I would recommend to turn off Stable Fit shadows for any style of game that isn’t a first person shooter or VR headset game. It’s especially bad for orthographic cameras because the cascade selection is based on some dodgy heuristic involving near and far clipping planes and our disabling the near plane on our Orthographic Camera totally breaks that heuristic.
(note: by my opinion Stable Fit is an outright cheat tailored to the FOV setting used for FPS and VR, where near plane is almost always 0 and far plane is also typically not so far from the near plane – it should probably be disabled for most third-person gameplay contexts as well as anything using orthographic perspectives. Why is it even the default setting?).
Secondly, disable cascades. Shadow cascades don’t work at all in orthographic cameras, since those depend on camera depth measurements, and orthographic cameras (surprise!) have no true concept of depth. If the cascades did do anything, it would be some nonsense behavior where shadows would cascade near the edges of the screen.
Finally, set Shadow Distance to a large value, like 10000. Again, none of these “camera depth” or “camera distance” concepts make sense in the context of an orthographic projection.
Tip #4: Editor Orthographic Scene View
Yeah, I know, this one’s going to be obvious for most folks. It took me a while to figure it out and, interestingly, Unity Editor does a much better job of switching between perspective and orthographic camera modes than the GameObject camera does. It even has this snazzy zoom transition thing! That’s probably worth a blog article to itself because you’ll notice it’s actually non-trivial to implement a similar behavior using the Camera GameObjects within the game itself.
(hint: I assume it animated the FOV of the perspective camera before hard-switching to the orthographic camera – combined with additional calculation to determine the orthographic size parameter as a function of perspective camera distance from an object, etc. – but I have not verified it)
If you come from a 3D gameplay or Unity background, this may feel obvious. But if you come from 2D/isometric gaming and art backgrounds, then you may have been thinking of orthographic projections in terms of the 2D angular components that form an orthographic illustration. What I mean by that is these 2D angles as illustrated by Wikipedia’s topics on Orthographic Projection (side).
Now is a good time to change that paradigm.
It’s true that you can develop Isometric gameplay within the context of what people have traditionally called 2.5D – a pseudo 3D environment where almost everything is 2D except a few specific bits and pieces needed to sell the illusion. This approach has its merits if you are developing your own 2.5D orthographic engine with a single fixed-function camera projection pipeline. We are not. We are using Unity, and Unity is all about full-3D environments, with full 3D models. These depend on 3D world space coordinates for our camera.
As a specific example, the modern physically-based material pipeline has specular and reflection features that depend on the camera’s full 3D position. If you don’t make an effort to handle your camera as though it exists in depth-honoring 3-dimensional space then you’ll likely have to avoid these effects entirely and use only Unity’s non-reflective legacy materials, such as Legacy Diffuse. While I’m sure it’s possible to develop a 2.5D isometric game in Unity, likely using 2D sprites instead of 3D models, this would be an exceptionally challenging task and is well outside the scope of today’s tips.
It can be helpful to have world axis orientation lines similar to those in the photo above. I made a lightweight component script to help me visualize those lines (extra helpful when paired with tiled floor texture)
Tip #6: Verify Your Camera Position in the Editor View!
Is your orthographic camera really where you think it is? If you’re basing it on what you see in the Game View (Camera Preview), then the answer is very likely “probably not”.
A perspective camera gives you depth perspective by which to help clue you in about the position of the camera within a world. If the camera is too close or too far from an object, well, you clearly can tell. The orthographic camera is not so fortunate: depth does not really exist and so there are no good clues about how far the camera is from the objects in view. In fact, given any specific view on your screen, there are literally an infinite number of possible camera orientations along a vector which will produce the exact same Camera View result. This can fool you into thinking you have a sensible position for your camera when, in fact, your camera could be a million miles away. Or it could be at 0,0,0.
Just for a bit of mind-warping awesome, consider for a moment the fact that you could — if so inclined — implement an entire Isometric Game without ever changing the height of your camera (Y=0 when following the Y=Up convention). To demonstrate this phenomenon, here’s an image of what might be a typical initial camera setup for an isometric view, pay attention to the Position of the camera:
right panel: y-axis (green) view from the side, with frustum is visualized by the white lines
Observe the camera position in the Scene view on the right panel – it’s nonsense, but the Game View and Camera Preview kinda look OK.
As you can see, the game view looks nearly identical even though the cameras are vastly different positions. It’s through this illusion that you can think you’ve rigged an orthographic camera correctly but then fail spectacularly when trying to execute a pan or spin around a variable pivot point on your isometric landscape.
So I strongly suggest paying close attention to your camera’s position and behavior inside Unity’s Editor View, at least until the general framework of your camera controls are rigged. Don’t just rely on what you see in that Camera Preview. It can save you time.
Tip #7: Orthographic isn’t a simplification, and some closing words
These tips are helpful for avoiding some pitfalls but are still a long way from rigging more advanced features of a good isometric camera. Isometric views have lots of advantages in terms of gameplay mechanics but are, generally speaking, an added layer of complexity from a game development perspective — unless you decide to limit your game to a handful of fixed-angle views a limited camera movement.
Unity3D compounds that problem, since it is built from the ground up in a manner that limits us from taking advantage of certain “orthographic hacks” that might otherwise be available to a custom 2.5D style game engine. If you are thinking of utilizing an orthographic camera as a means to simplify your game — for example making it “less 3D” and thus less mathematically intimidating — then probably don’t do it. Orthographics in Unity3D become the worst of both worlds: you have to rig everything up as though it’s full 3D perspective, and you have to then filter it through an unorthodox reprojection matrix that hides visual information from you about the state of your world.
It’s my experience so far that robust isometric view game development requires an even stronger grasp of 3D math and methodologies than games built on 3D perspective views. Sure, Orthographics offer gameplay and artistic advantages! But be sure to weigh those vs. the added complexity of rigging cameras that can play by all the weird rules of depth-aliasing.