UnityUtil

Background

This library is essentially a collection of utility classes and components that I've been building since I first adopted Unity in 2016. Back then, I was working on a first-person shooter, so I wrote several components related to inventory, ammo/health, projectile spawning, etc. As I started adding more general, utility components (for logging, dependency injection, PRNG, file I/O, etc.) and working on games in other genres (particularly the mobile game, High Hand Hold'em™) I decided that these components should be moved to a separate, open-source repository for reuse between projects.

The name of this library has gone through several iterations. First, it was "Danware.Unity", named for the short-lived company, Danware Creations, LLC, that I founded before my partner and I founded Derploid Entertainment, LLC. In January 2018, I renamed this library to the organization-agnostic "UnityUtil", but the namespaces were all still under UnityEngine.*, which I thought would be simpler for consumers of the library. Finally, in May 2022, I decided that this was actually more confusing (it might not be clear why an API is unavailable if UnityUtil hasn't been referenced) and eventually renamed all namespaces to UnityUtil.*.

In late 2022, I started getting more serious about documenting the library and making it publicly consumable. After discovering the awesome OpenUPM project for hosting UPM packages, I created a UPM manifest for the package and made plans to distribute the library that way.

As of this writing in January 2024, the library is still a bit of a "monolith", with all of the logic described above contained in a single assembly (DLL). Once my partner and I publish High Hand Hold'em™ (meaning UnityUtil has been used in an actual published game), then I will break up the library's UnityUtil.* namespaces into separate packages and release 1.0 versions of them to OpenUPM.

Technical Details

I am proud of several technical details in this library:

  • General code quality. I have taken great pains over the years to keep the codebase clean and up-to-date with the latest .NET/Unity APIs and C# language features (such as interpolated strings, null-conditional operators, file-scoped namespaces, etc.), use consistent formatting and identifier naming, prevent duplication and follow SOLID object-oriented design principles, etc.
  • Widespread use of the dependency inversion principle to keep the code loosely coupled and testable.
  • My custom utility systems, primarily those for logging, dependency injection, and input mapping. After discovering UnityNuGet, which allows much simpler use of NuGet packages in Unity, I am starting to replace these systems with the standard Microsoft.Extensions.* libraries. Still, I now have a very solid understanding of how DI and logging systems work in general, and the Microsoft ones in particular. The input mapping system is being replaced by Unity's newer InputSystem UPM package.
  • Use of MSBuild properties/targets throughout the project files to reduce duplication of language/reference versions, project configurations, etc.
  • Extensive test suite. As of this writing in January 2024, there are a combined ~550 Play Mode and Edit Mode tests. Some of my older, more niche components do not have tests, as I hadn't learned about the Unity Test Framework in 2016 and was still fairly new to unit/integration testing. All new code is thoroughly tested though.
  • Thorough API documentation. Again, some of my older, more niche components do not have API docs, as I was still new to C#'s XML documentation syntax in 2016 (and some APIs are pretty straightforward based on their names/signatures). More holistic documentation (mainly in the project README) is still on-going as of this writing in January 2024, but I pride myself on writing well-organized docs that are both detailed and clear.