What is Unity engine? (quick overview)
Unity is a popular development platform that can be used for free (with some exceptions). It provides a set of tools (assets, plugins, libraries), the majority of which can be found on GitHub, Bitbucket, the Unity Asset Store and other similar platforms.
A large community around Unity with its rich knowledge base allows finding ready solutions for common errors in no time. There are also lots of guidelines for new users, which make Unity a good starting point for beginners, learners and amateur game developers. The wide pool of possibilities that this engine provides opened the way to new professions such as technical artists, gameplay programmers, UI programmers, and network engineers.
Business-wise, Unity is a good free option for small and medium-sized companies whose gross annual income is not higher than USD 100,000. Only when a company exceeds this amount it is required to switch to the paid version of the tool.
Is Unity engine really that bad as people are saying?
Many developers don’t consider Unity to be an ideal engine for creating mobile applications, in particular – utility applications. Indeed, this engine was created mainly for game development. Although there are many sceptics who also question the quality of games on Unity engine.
In our opinion, it doesn’t have to be the fault of the engine itself. More often it’s a result of the very low entry threshold for creating applications on Unity. This factor in combination with the lack of programming experience leads to a high number of poor applications and games created on Unity engine.
For this reason, Unity is often referred to as an “easy to learn, hard to master” platform. The application development process in Unity can be compared to an avalanche: the more experience the programmer has, the more this application grows and gains quality.
Common pitfalls in Unity
Building UI with Unity
Even though the engine is generally very friendly for beginners, there are many bad programming practices that an inexperienced developer can easily step into. One of such pitfalls lies behind creating a user interface (UI).
Overall working on UI in Unity is easy but only to a certain extent. When creating UI for the needs of the majority of games, you most probably won’t encounter any troubles. However, for more comprehensive and scalable solutions, it will require a lot of work since UI tools in Unity are not so developed, standardized and automated.
You won’t find any structured UI in this engine like in others (e.g. Xcode for IOS), but we believe it will evolve over time and switch to something like HTML/CSS.
The UI tool in Unity is flexible but not suitable for every project. All in all, it is a gaming engine and is therefore not universal. For more complex tasks a custom approach is usually required, such as creating UI on your own or using external solutions for that.
Challenges in achieving clean code and architecture using Unity
When working with Unity, achieving clean architecture and code might be a challenge. Without programming experience, you easily end up with chaotic architecture or no clear thought-through application structure.
The Unity environment itself does not encourage or help programmers apply good programming practices. Often newbies take shortcuts using primitive solutions such as operating mainly on static classes, abusing singletons or storing logic in one file consisting of thousands of lines of code, trying to justify such behavior by “done is better than perfect” principle.
Creating effective architecture and advanced functionalities in Unity, similar to UI creation, requires learning certain conventions (e.g. design patterns) and interest in available plugins, unless you want to waste your time breaking open doors.
In a situation when let’s say, you want to do a good job with InputField, you still have to write your own plugin that will handle it well. Let’s take a look at the example of building a mob app (e.g. on Android). Unity does not properly support InputField objects by default. When you select such a field, you lose “focus” and you cannot change the cursor position, for instance, because the system keyboard has appeared. A typical solution is to use an additional InputField that is built into the keyboard. So if you want to avoid it, you need to write a native plugin that will handle the field in the right way.
Difficulties in applying SOLID principles in Unity
Due to its architecture, Unity makes it difficult to apply SOLID principles*.
*Five principles of Object-Oriented Design: SRP – Single Responsibility Principle; OCP – Open/Closed Principle; LSP – Liskov Substitution Principle; ISP – Interface Segregation Principle; DIP – Dependency Inversion Principle.
This mainly applies to references between objects, where without the typical “static void Main() { … }“ in which an application starts we can face a problem of sharing references between objects. A typical approach would be adding references from the editor. But in the long run and with the development of the project, this can be a very bulky solution that causes many errors.
Especially bad practice here is the abuse of the UnityEvent class, which allows you to subscribe from the editor. A seemingly convenient approach can quickly cause the illegibility of information flow in our code, whereas juggling with dependencies leads to classic spaghetti.
Threading in Unity
Unity and its native objects are not thread-safe, which means we cannot use them other than as our main thread. On one hand, this protects programmers from poor use of multi-threading. On the other – it cuts off several important ways for optimization.
Parallelization of calculations is useful, for example, in the case of heavily burdening mathematical calculations. However, if we want to break down work on a specific native object into several frames, Coroutine – a way to write many asynchronous and delayed tasks – comes in handy.
Anyways, multi-threading should be done with big caution because it can work counterproductively. For example, creating more threads than there are processor cores in applications is pointless, and switching between threads is also additional processor cycles.
A large part of operations is dependent on each other, but it makes sense to separate and transfer to other threads particularly important operations, such as the procedural model generation.
Using modules and Unity version control problems
Unity allows you to use modules typically associated with devices, such as IMU (sensors), but only at a certain level of abstraction, which leads to multiplatformity. If we want to use services specific to this platform (for example, Android, iOS), then native plugins will come in handy.
An example here would be getting detailed information from a GPS module (like the number of satellites available) or from a fully functional WebView. For devices using the Android system, we may be interested in classes such as AndroidJavaClass and AndroidJavaObject, which allow creating simple plugins at the project code level.
Many developers are also complaining about Unity version control problems. Luckily, this problem has already been solved. The engine is getting better and better and subsequent versions appear every year.
What Unity is good for?
There are many opinions on the Internet regarding the advantages of using Unity, such as cross-platform. In our opinion, this is not the most important feature as many other environments offer it too.
What is worth emphasizing is that Unity is a very well made engine that works perfectly on both iOS and Android. Just remember that in the case of iOS applications, you need to have a Mac to build a project for testing.
Overall, Unity is a good and convenient tool with a very low entry-level. It is accompanied by a lot of well-described tutorials and its own learning platform.
The engine works with C# but you can alco use many languages, such as C ++, Python, Java in form of libraries, and is compatible with various operating systems (Windows, Linux) and devices (such as Chromebook, Mac). So we basicly programming in C #, it is easy to find solutions to problems, not only within Unity resources but also in the documentation and articles related to the language itself. Besides, thanks to Garbage Collector in C #, we don’t have to worry about engine memory leaks.
The platform works great when it comes to prototyping. The app prototype can be sketched very quickly* without the need for creating the architecture. However, the problem can be a very fast script flow.
*Due to its approach to objects and built-in classes Unity works great for rapid prototyping of applications and games It is especially important for AR / VR applications developments where we can practically test the concept of some functionality on the device right away. However, you should keep in mind that rapid prototyping might lead to poor project architecture.
Easy debugging (especially when it comes to logic and UI, e.g. rendering threads) is another advantage of Unity over other engines such as Godot, Unreal. A great tool for assessing the status and optimization of your application is the built-in Profiler, which allows finding bottlenecks.
Despite the unstructured UI, the engine has well-resolved UI responsiveness. It allows us to define the arrangement, scaling and behaviour of containers from the editor level easily (e.g. stretching to the size of the window).
Unity is a multi-platform environment and works great for creating cross-platform AR/VR applications, mobile games, console games, due to the possibility to create 3D graphics with a relatively small amount of work in a very easy way without extensive programming knowledge needed. This is not a case when programming in Android Studio for instance.
The resources available in the ML-Agents module reduce the barriers faced by the developers of machine learning applications. Learn more about our machine learning application cases here.
Conclusion: so should I use Unity?
It might look like Unity is not the best tool for creating mobile applications and it is a rather common opinion. However, more and more game studios use the Unity engine, as well as offer job positions for Unity engineers.
The reasons for that among others are: the dynamically developing Unity has a low entry threshold; it has a large pool of free learning assets and quite pleasant documentation.
Despite the fact that the engine is not perfect for creating utility and native applications, there are applications for which it works great, e.g. when creating cross-platform AR/VR applications running on multiple AR/VR devices. Prototyping applications and creating 3D games on the Unity engine has also a lot of advantages.
Real case of using Unity for creating a cross-platform AR application
At NeuroSYS, we’ve chosen Unity for building one of the core components of nsFlow – the platform for creating AR applications. nsFlow, generally speaking, is an Industry 4.0 solution that streamlines knowledge management for industry, using augmented reality to provide the industrial workers with the necessary knowledge anywhere and at any time.
nsFlow offers two functional modules: Workflows and Remote Support. The Workflows module allows clients to model real-world processes (hands-on training, service or maintenance procedures, etc.) using a dedicated Workflow Creator tool, and then deliver them to workers equipped with AR glasses, so they can use them as a training tool or assistance in their day-to-day work.
The Remote Support module breaks the barrier of the distance separating line workers and technicians from experts who could help them in unusual situations happening every day, giving both the possibility to consult over technical problems remotely using audio-video communication and handy visual tools for experts to guide technicians step-by-step straight to the desired solution.
From the very beginning, one of the core principles of nsFlow was to be hardware-agnostic. The market of AR devices changes rapidly every year so we didn’t want to stick to specific hardware and chase the market by implementing newer and newer versions of our AR app every time a new device is announced. In order to achieve the high independency from hardware we made two strategically critical decisions:
- the architecture of the platform must limit the responsibility of the AR device and AR app to an absolute minimum, making it just a thin client, commanded by the central engine installed on a server,
- the AR app must be built in a cross-platform technology that will allow us to onboard new devices with the least possible efforts and costs.
Unity met the second assumption perfectly. It gave us a strong foundation for all nsFlow AR and mobile apps, allowing to share most of the mechanisms and, as a result, manage single source code for six different devices (Microsoft HoloLens, Vuzix M300, RealWear HMT-1, Epson Moverio BT-300, Google Glass Enterprise Edition 2019 and Android smartphone).
Moreover, Unity, as a games-oriented platform, provides a lot of tools and solutions that are extremely useful when building AR applications that have a lot in common with games (i.e. 3D scenes, physics, graphics, rendering, etc.). In our case, Unity was a perfect fit, however, it was a long and bumpy road until we domesticated that technology together with all its specificities.
You can read more about nsFlow and see what other challenges we, and Unity itself met and how we faced them up.
To sum up…
In the world of technologies, there are no purely “good” or “bad” decisions. Every choice shall be made based on the wide range of project and business needs and considerations, and it’s often a compromise.
Despite all its pitfalls, we wouldn’t advise file Unity away in storage, as it has lots of advantages for specific applications as those we described above. However it should be always a conscious architectural decision to use this technology and there shall be strong arguments supporting it.
We hope you enjoyed this reading. Feel free to leave your opinion below regarding Unity or go directly to our Unity service page to get to know more. We will be happy to continue the discussion.