Building A Camera System For Unity
Although I haven't posted to this DevBlog recently, work is very much happening on the tactical space RTS. Recently, I implemented a full camera system for the battle portion of the game and wanted to share my thoughts on it here.
Originally, I had intended to use and stick with camera assets from the Unity Asset Store. After becoming more proficient in coding, as well as understanding the pitfalls of relying on third party code that may not be updated or have the features I want, I decided to roll my own camera system. I bought 3 different camera assets (scripts) from the Asset Store and have absolutely no regrets having done so. In fact, they were instrumental and helpful in building my own system since their source code is provided. I'm grateful for the opportunity to learn from other programmers and to see how they approach such tasks.
The first asset I bought was the KGFCameraSystem by KOLMICH Creations, which was on sale. I like all the various features that are implemented in this camera system, and may decide to use it or at least parts of it in a future game. However, since I like to keep my project as clean and streamlined as possible, the framework seems a little too heavy for me, and the code is a little difficult to follow for a novice programmer like me. Also, it may be just my system, but in the web demo and in the Unity editor, running the scene with vsync enabled causes slight stuttering every once in a while, which doesn't happen with other camera assets or with vsync disabled.
After playing around with the demo for RTS Camera Pro by Voxel Frog, I loved the smooth feel of the camera. I contacted the author with some questions about its usefulness in a space RTS. The author was super friendly and helpful, and mentioned that he was working on a camera system dedicated for a space RTS. He sent me a demo to play around with, and I gave a lot of feedback. He eventually released it in the form of the asset SpaceCam. I ended up buying both of these assets. I was going to stick with SpaceCam as it has a lot of features, but there are a few issues with it - some allocations every frame, as well as the inability to rotate while transitioning to focus on an object, which wasn't a problem in RTS Camera Pro and KGFCameraSystem.
As of the time of this blog post, both RTS Camera Pro and SpaceCam have not been updated in around a year. This is when I made the decision to make my own, based on the features I've seen in many strategy games as well as in these assets. Here was my process:
1. Starting with a blank slate, I wanted to create a simple orbit cam. I found these resources online which helped me understand how to implement it: 1, 2, 3, 4
2. Once the orbit cam was organized in a way that made sense to me, I started going through the source code of the camera assets, especially RTS Camera Pro and SpaceCam, to see how certain features were implemented. I realized that I could go with one of two different approaches. The first is like with KGFCameraSystem and SpaceCam, where movement is done by manipulating the camera's transform directly. The second approach, which seems to be what RTS Camera Pro and some space strategy games use, is to have the camera focus on a GameObject, and camera movement is done by translating the transform of that GameObject, with the camera following it. This second approach is the one I settled on.
3. I then started implementing each feature one by one. This required a lot of testing, internet searches for clarity, refactoring, etc. to get each feature just the way I wanted and in a way I'd be able to understand when I revisit the code in the future. The features include dampening, transitioning, following, limits, boundaries, zooming, focusing, panning, obstruction, etc. I faced a lot of hurdles along the way, but through persistence and several AHA! moments when taking showers, I was able to overcome each one.
4. I really liked the free flight feature in SpaceCam, and wanted to implement that as well, but the approach I took in #2 above didn't immediately lend well to this. I spent a good part of a day messing with quaternions and euler angles trying to get the feel the way that I wanted, but there was always some slight problem with it. In the end, I came up with a creative solution of having the GameObject basically moving to the camera's position (rather than the other way around), and since it's so close to the camera (but invisible), it gives the feeling of directly controlling the camera's movement while flying.
I spent some time trying to implement turning to face a new object that is selected, but was having some anomalies arise in the process when transitioning from certain angles. I then looked at Homeworld 2's camera movement and realized that the way it was already working in my system is the way that Homeworld 2 does it, and decided to scrap all the work that I did that day.
There are still a few more features I'd like to implement. For example, collision detection while in flight mode, camera tracking, and camera shaking. I also need to make a decision about whether or not to have collision detection while rotating based on how it affects the feel of the game. I needed a break though, and since Maya LT 2016 came out, I wanted to start 3d modeling and texturing to exercise the artistic side of the brain. Although I feel that programming really exercises the logical side, I've come to understand that there is a lot of scope for creativity within it as well. Thanks for reading!