What I Love about Unity

Posted on 

Unity Engine is really great, despite all of it's flaws. It's very impressive with how many platforms it supports, it's wide range of features, the insanely huge community surrounding it and of course all the great games and experiences produced with it.

So here are the things that I love about Unity:


Ease of Use

Unity is super accessible and for the most part, very easy to use after you get past the initial phase of figuring out how to do anything and where stuff is. It's also has a quite lightweight runtime + editor, allowing for far more machines to use it than other engines, eg. Unreal Engine, which has a heavier focus on cutting edge techniques/technology, hence generally requiring more powerful hardware.

Documentation

Although I do sometimes get frustrated with some out-dated examples being present or barely any info on some systems, the documentation is for the most part is nicely maintained and generally answers most of my questions before having to look elsewhere which is a great thing. For beginners it might be a bit bland/verbose but once they're aware more specifically what they're looking for, the documentation is great!

Community

I would argue that Unity's community is the largest out of all the major game engines, mostly due to it's lower bar for entry, having been free for the longest and dominating essentially all types of games other than triple-A, where Unreal is undoubtedly the better choice in most cases. This is great, especially as you're learning the engine or even game development as a whole as there is some really great content to learn from for almost all aspects in one way or another.

C# Scripting

Compared to Unreal's use of either visual scripting via it's Blueprints (which is excellent from my extremely limited experience) or scripting via C++ (too much of a learning curve for me at the time I used it), Unity's choice of C# is generally great. It's quite accessible for most basic things, allowing artists/designers to make simple/quick edits easily.

A huge benefit of C# vs. C++ for gameplay code is that you generally don't need to maximize performance as much since all the more intensive engine functions you use, will actually call C++ code via interop. That being said, there is sadly quite a high performance hit for various engine functions due to the interop between C# and C++, eg. creating/destroying or even enabling and disabling gameobjects is pretty demanding + causes garbage allocations (this is being addressed in it's DOTS ecosystem of packages!).

Push Towards Scalability/Full Usage of Hardware

In the last few years, Unity has been working on various ways to push the boundaries of what is feasible within the engine. A large limitation of the engine before this push is that the vast majority of functions/systems that you use via C# scripting must be run from the main thread, drastically reducing capabilities to do multi-threaded C# code. Most of the new systems/features are trying to address this and many do drastically help in key performance critical areas, as listed below:

Job System

Unity's traditional core engine uses C++ with a Mono runtime that runs all the developer-created/imported scripts which can communicate with the core engine. This is generally good enough for most things, but a massive limitation of the standard C# runtime is that all engine functions that interop with the core C++ engine must be run from the main thread. This limits the vast majority of C# scripts to also run on the main thread, thus preventing efficient scaling for multi-core hardware. This has become an increasingly more and more relevant issue within the past decade as now ~90% of gaming computers having on average 4+ physical cores (see physical CPUs) (and ~55% have 6+ physical cores!) and the current generation of consoles having 8 physical cores. This is especially important since the last decade has seen a massive slowdown in single-core performance compared to previous decades.

Unity has ways to utilize multi-core hardware for various parallelized algorithms/functions via it's Job System; It allows you to write multi-threaded code in C# that can still interact with the core C++ engine from other threads. It also has various checks/enforcements to best "enforce" correct multi-threaded code, since the subject is notoriously specific with it's approach/requirements.

Burst Compiler

In addition to the Job System, Unity also has a Burst Compiler package that allows you to translate your C# Job into highly optimized native code via LLVM. This combined with Unity's Mathematics package allows the Burst Compiler to produce vectorized/SIMD (Single Instruction, Multiple Data) mathematical operations, often drastically improving performance for various computationally taxing algorithms. The Burst Compiler does enforce more strict requirements for this to work however!

I personally am utilizing it quite a bit for my game's modified diffuse limited aggregation algorithm. I'm using it to produce unique levels during runtime with random seeds and it improves the performance by around 30x on my 8-core CPU, which is incredibly impressive!

IL2CPP

Unity also has a build setting that allows you to translate all of your scripts from C#, the Intermediate Language (IL) into C++, reducing the overhead from the C# runtime (Mono in Unity's case, due to it being cross-platform, although the newest .NET framework, v6.0 is also now cross-platform and I believe Unity has plans to transition to it in the future). There are a few limitations, such as reflection not working as a side-effect of translating the code to C++ (at least that was the case when I last tried it in mid-2021).

Compute Shaders

Now compute shaders aren't exactly a new thing to neither Unity nor graphics programming but they're becoming more and more applied to various aspects of compute intensive applications, such as games. They very effective for parallelized algorithms and scale much than multi-threaded CPU code as GPUs are highly parallelized by design and from my limited understanding, are improving at a faster rate than CPUs by now.

DOTS

Data-Oriented Tech Stack (DOTS) is Unity's latest effort to drastically improve the engine's scalability and performance. It's a series of packages that are meant to work together to allow for much better usage of hardware by moving away from traditional OOP (Object Oriented Programming), towards a more data-oriented design (DOD), which also happens to transfer to multi-threading much more easily.

The basic idea is that instead of having all your data fragmented between each gameobject/class, each property is in sequential order in-memory and then you iterate over all those properties in sequence, taking advantage of how CPU cache lines work by maximizing CPU cache hits.

Diagram showing memory layout comparison between OOP and DOD

It's much more complicated than that but it greatly improves performance by minimizing the amount of times data has to be fetched from RAM since it can take hundreds of CPU clocks whilst it has to wait. Although modern CPUs try their best to do things whilst waiting for the memory to be loaded into cache, it can't always, thus greatly wasting many clock cycles. Unity has a great talk about it in more detail here since I only summarized it very shortly here!

Sadly DOTS, well specifically the Entities package, (it's the core part of the tech stack) is still only in preview and likely will be for over half a year still. It's also not supported by all platforms (yet!). It's API has seemingly calmed down though, compared to a year ago, when many tutorials/guides less than a few months old would have outdated API.

Note: So I only saw that the Entities package (finally!) got it's first proper update in a very long time (almost a year it seems) for GDC 2022. I actually might move some of my code to use it since my game relies on a ton of gameobjects for the level and whilst I've made various optimizations to reduce the overhead, the major performance sinks are still the actual instantiation of objects and physics. The Entities package would address both (well im not sure if ECS physics is ready for 2D yet) so I'll definitely at least check it out!

Cross-Platform Abstraction

Unity makes it incredibly easier to port/export your game to different platforms. Some platforms might have missing/older hardware so some features aren't accessible to every platform, but the overwhelming majority do. Unity is also often pretty quick to add support for new platforms (at least for the latest editor release) which is always nice to see. I know this is very common between most other game engines but it's still such a great feature to have!

ShaderLab

Unity has a custom shader format that declares properties which can be exposed in the editor, and then HLSL shader code which is transpiled to the target platform's native shader language. There are also various Unity engine properties that you can use and defines can be used to exclude/include code blocks for certain platforms (or you can also directly create custom shaders per platform too).

Player Runtime

The player runtime converts all the platform abstractions to the native platform. There is both a mono (C#) runtime, which uses the scripts as is and a IL2CPP runtime which converts your C# code into C++ during the build to reduce the overhead you get from having a runtime-based language like C# which has to convert your code into bytecode just-in-time (JIT) and then natively execute on the hardware, whilst C++ is compiled before hand, removing the need for JIT.

Editor

Unity's editor is the way you combine all the individual assets, scripts, settings together to create the game/experience you're working towards. It's available for the 3 major desktop operating systems, Windows (x86/x64), Mac OSX (x64/arm64 (seems to have more bugs/crashes)) and Linux.

Easy to Use

The Unity editor is pretty easy to use after initially learning it's layout and the engine's approach. It's layout and windows are customizable like any good editor/tool should be and features various built-in tools/settings windows.

It also features various built-in tools for various situation such as tilemaps, terrains, customizing settings, gray-boxing geometry for level design, adjusting sprite properties, setting up animations, etc.

Extendable

A huge feature that Unity's editor has is the ability to code custom editor windows and inspectors via C#. This can be incredibly powerful for building in-editor tools that aid all sorts of parts of development. It can be used to add support for custom data/script types in the inspector and for designing entire systems such as localization and content editors. Very powerful and useful for both programmers and other teams such as artists, level designers, audio engineers to better mold the engine to enhance the workflow for your projects.

Cross-Genre Framework

Unity doesn't really lean towards any specific genre or style of games and whilst this can limit it's toolset to be less narrow/in-depth, it's super beneficial to be able to create almost any type of game within a single engine/ecosystem of tools, which makes the engine more worth your time learning than a dedicated genre game engine might be if you're interested in making other types of games/experiences.

Built-In Systems

Unity has various built in systems/tools that really increase accessability for features and accelerate development time for creators. My personal favorites include:

Visuals/Rendering

Unity's visual options are pretty impressive, they offer rendering abstractions for all the supported platforms with a single shader language, ShaderLab. Theres an extensive animation system, for both 3D models and 2D sprites/textures. If you decide to use one of Unity's render pipelines, either URP or HDRP, you'll be able to use many of the new editor features such as Shader Graph, VFX Graph and have much deeper control over the render pipeline (generally a good thing but sometimes a little much for seemingly simple tasks/features).

Shader graph has been especially helpful for me since I've used Blender's node material system in the past and find it much more intuitive and visual than programming the shaders by hand.

Physics

Now I'm quite bad at using Unity's 3D physics system for anything more complicated than a player-controlled kinematic rigidbody, but that's on me. It's already quite performant and they also have a dedicated subset of the physics engine which is optimized for 2D. They also have an experimental job multithreaded mode for 2D physics, which I benefit quite a bit from in my game. And with DOTS, they're switching from PhysX to Havok, along with a (planned) multi-threaded solution, specifically for DOTS entities.

Pathfinding

Unity has a really nice system for easily building navigational meshes (nav-mesh) for efficient pathfinding. It has various settings for agents to define what behavior they're able to perform and even has support for runtime generation/updating of nav-meshes.

UI

Unity already had a pretty nice runtime UI system but it very recently got a successor, UI Toolkit, which is more similar to web-development in terms of hierarchy and style/layout engine with it's use of flex-boxes and style sheets. It's missing a few quality of life features but I personally find it already much better than the old system in terms of styling and responsive-design. It also has a really nice visual editor called UI Builder for building UI layouts quickly. It also seems to handle updating the UI layout more efficiently from my very limited testing.

ScriptableObjects

I saved the best for last. ScriptableObjects are honestly the best thing in Unity for me. They have soo many uses, from shared variable containers with change events, to general data containers, or hot-swappable logic for AI systems. They really help with iteration speed with my projects as I can easily edit data between multiple prefabs/systems quickly and swap in and out items/skills and behavior systems with ease for faster experimentation.