How (and why) I'm rewriting Unity documentation

Oliver Oliver • Published one year ago Updated 8 months ago


Update 14 September 2023

Due to Unity's absolute shit-show of decision making, I have decided to cancel all Unity-related projects. Unfortunately, this is one of them. I'm sorry to say this will not come to fruition.

Let's get this out of the way: Unity docs are atrocious.

Seriously, I can't believe Unity lasted this long with documentation so lackluster, so half-assed, so incomplete. At least it's not as bad as Unreal's documentation though, but that's a story for another day.

The current mess

To show exactly what I mean, consider the documentation for the generic version of GetComponent right up until 2020.3:

“Generic version of this method.” Yeah. No shit

Now, admittedly, this is outdated. Today, there's actually a helpful description in its stead:

I mean... it's not wrong but it's still wrong.

But I still have gripes with this though. Namely, the signature is incorrect. T isn't an inherited parameter from the declaring class, it's distinct to this method, so the correct signature is as follows:

public T GetComponent<T>();

You can't just ignore generic type parameters, Unity, god damn.

It doesn't end there though. The signatures for many of the members in various types are just blatantly wrong. Consider the position property of the Transform class:

Yes, I'd like to switch to Manual. Automatic transition is for peasants and people who care about the environment by buying EVs. Nerds!

Because of how this declaration is written, if you didn't know any better, you'd be led to believe this is a field. After all, this is the syntax for declaring a field. You have the visibility modifier, the type, followed by the name, and terminated with a semicolon.

But no, you're wrong. This is in fact a property. The correct syntax that should be written here is:

public Vector3 position { get; set; }

And I mean, you could optionally include the extern keyword as this property does call into native code since the majority of the Unity engine is native, but honestly that's irrelevant to the caller. The fact of the matter is, position is a property that has both a get and a set accessor, both public, and so yes it kind of behaves like a public field - but it isn't one. And that's an important distinction to make.

You know what's worse though? You know what really grinds my gears?

Head to the docs for UnityEngine.Vector3. Go on, I dare you. I'll wait.

Did you notice it? No?

Here I'll show you:

Why the fuck you lyyyying?

The x, y, and z members are grouped under “Properties”. THEY ARE NOT PROPERTIES.

THEY ARE FIELDS.

WHY DOES UNITY CLAIM PROPERTIES ARE FIELDS, AND FIELDS ARE PROPERTIES?

Oh but it gets worse. Let's mention the fact that a lot of the Unity docs fail to mention very important details. Like how Debug.Log accepts an object which means any value types you pass to it get boxed.

Yes, seriously.

Even something as innocuous as Debug.Log(42), will box 42 creating an allocation. But wait, there's more! ToString() is then called to produce a string representation of the object which creates another allocation. So congratulations. Whenever you simply log player health or player score, you're killing performance by not just calling ToString() yourself (or using an interpolated string, whatever floats your boat.)

There's a reason Console.WriteLine has so many overloads accepting so many types. All built-in numeric types get special overloads, to prevent boxing. The object overload is a last-resort:

They were on to something, y'know.

This is just one of the many important details that Unity fails to notify its developers of. I could be here for hours. But I'd rather move on.

There's hope yet!

I don't think it's unreasonable of me to say that Microsoft are the kings of excellent documentation. Microsoft Learn (formerly Microsoft Docs, formerly formerly MSDN) is so well made, in my opinion it sets the bar of how docs should be written.

I once created a proof-of-concept design, showcasing how Unity docs could be good, by using a style heavily inspired by Microsoft Learn.

Documentation. As it should be.

Seriously, why does this not already exist?

How did I accomplish this?

To be honest, it was a massive hack. I created a Class Library project named UnityEngine.CoreModule (so the assembly name could be displayed as that), and began writing out the boilerplate of all the types and members that Unity has to offer. I wrote xmldoc for it all, and used docfx to generate documentation files from the source xmldoc.

However, the front-end was a custom ASP.NET Core app. I didn't use docfx to present a static doc page, as you might have expected. I had my custom front-end read the intermediate format provided by docfx coupled with a metric fuck ton of custom CSS for the styling, and topping it off with HighlightJS to render codeblocks for the type and member signatures.

I soon realised, however, that this would be a mammoth task to do. Rewriting the entire Unity assemblies just to get documentation is a waste of my time.

Ditching DocFX

I knew if I were to succeed in making Unity docs not suck, I'd have to come up with a more efficient pipeline.

So, for a little while now I've been working on a tool which can generate the declaration syntax for any type or member. In essence, I'm writing a tool to provide me this string:

Does anyone actually use this method?

You'd be surprised at how few tools exist to actually do this. So I wrote one, and it's open source.

But I didn't stop at C#, oh no. The tool also supports VB.NET, F#, IL and C++/CLI. Why? Because the Microsoft docs allow you to view the declaration syntax (and example snippets), in any of these languages:

Except IL. For now...

If you look at the signature for Console.WriteLine(string), for example, you'll see this:

I like how HighlightJS thinks value is a keyword here. In fairness, it is a keyword, but only inside a property's set accessor.

But change the language to C++/CLI, or VB.NET, and you'll see the syntax change:

^ is such a useful operator.

Public Shared Dom

Now your immediate question might be, “why would I need the syntax for Unity types in languages other than C#? Doesn't Unity only support C#?”

Kind of. It's true, Unity is only bundled with a C# compiler. Code written inside the project can only be C# and you'd be forgiven for thinking that's all you can use.

But forget not, Unity hosts the .NET runtime (specifically, a fork of Mono as of the time of this post) to actually execute your compiled code. This means you can use any .NET language that compiles to IL.

F#, VB.NET, C++/CLI, hell you could use IronPython if you wanted. As long as you prebuild the code to a .NET .dll, you can place that .dll into your Assets as just another library. You can technically write your game in any .NET language if you so desired. It's not common to do, but it's possible and there's nothing stopping you from doing it.

So anyway, the tool I wrote supports these major .NET languages. For example, take a look at the declaration syntax for one of the GameObject constructors:

C++/CLI is happy ^> ^

And the correct syntax for Transform.position:

This brings me great joy.

Epilogue

Once this syntax generator is working correctly for all languages, I'll be utilising it along with an assembly scraper to extract every single type, and all of its members, from my Unity install directory; to generate the documentation files needed for the front-end to eventually read and display just like my proof-of-concept. Fortunately, the brunt of the Unity docs is available in offline files too, in the Unity install directory, placed conveniently alongside the assemblies. I can use this as a starting point, and begin to rewrite the parts that need rewriting over time.

Once I have a very basic version of the front-end up and running, I'll be deploying it to my VPS and hosting it for the public for the foreseeable future. It will also be 100% open source when that time comes, so I will accept anyone coming in and contributing to making better Unity docs. I know I cannot do this by myself. It would be foolish of me to assume otherwise. But I also know I'm not the only one who wants to do this, and I'll take all the help I can get. And of course, I'll be writing more blog posts as I make progress on this project. So stay tuned.

Unity has the potential to be such a great engine. It has the potential to be a positive development experience, as it's one of the very few capable engines out there for C# / .NET. Let's make the docs what they should be, what they deserve to be, for everyone's sake.

To Unity: if you want to hire me for this, I'll await your email.




3 legacy comments

Legacy comments are comments that were posted using a commenting system that I no longer use. This exists for posterity.

chicdead26 chicdead26 • one year ago

Wow, Yasa, i'm disappointed. I thought you would dedicate about four paragraphs on how Unity does not know how to lerp…

In all seriousness, i do have a problem with Microsoft's documentation as well. I sincerely think they have a tendency to overcomplicate their examples. They are very well constructed and all, but still overcomplicated.

I wish this gets off the ground, and i might make some contributions myself. Best regards, Yasa!

Oliver Booth Oliver Booth • one year ago

I'm confused, what makes you think Unity doesn't know how to Lerp? Their documentation shows the correct usage 🤔

As for the overcomplication, I can see what you mean. Hopefully in this rewrite project, example snippets can be clear and concise rather than verbose and including irrelevant elements.

Edit: And of course, your contributions will be welcome!

vale vale • 8 months ago

yo, yasahiro(Oliver), uhm, when you're avaible can you add some documentation for compute shaders?