I’ve been working with Unity for years, in projects of various sizes. Work on editor extensions has always been a struggle. The life cycle of most things is not defined and/or rigid, and discovering what you need, in what order or when it needs to be called is 80% of the work.
Using Reflection, or even Harmony to patch Unity live, has almost become the norm when working with Editor Tooling.
Edit: reworded below to better communicate that I don’t think the issue is in a single developer, but the overall approach to things and/or review process.
I’m writing this post after having worked with the EditorTool API and again being frustrated with the design choices made in its API.
This isn’t a remark on the author of that API. I suspect that the choices he made were due to technical limitations or having the requirement of staying in-style. However, I want to address the problem that even in 2020, Unity is using a style and design of coding for a platform that is presumably intended to be extendable - however is anything but. I want to discuss what needs to be done so we can avoid having to use this type of design.
I hope that this post sparks somewhat of a discussion on Unity’s API for the editor, or, at the very least those parts that are extendable.
As an example of this issue, I want to point out the relatively new Editor Tool API.
In this post , a Unity employee is outlining a pretty fundamental usecase: a Tool detecting whether it is activated or disabled. This functionality is hidden behind a global event handler and a somewhat unrelated external state check. How to implement this pattern is not mentioned in the official docs, only in a post on the forum.
- I don’t understand why listening to the lifecycle is not API that can exist on the EditorTool itself. I.e. a method to override given that we already inherit from a base class.
- If it is not, why is the event handler not providing context on where it is switching from and to. This design would be both self-documenting (instead of the programming needing to lookup the active tool through an unrelated other variable) and functional (not dependent on outside state).
- Where can I find the documentation on what will be called, when?
Note that my issue isn’t solved by updating the documentation.
My problem is with the approach to code design. The “simplicity” is taken to such an extreme that it actually hurts implementation time because developers need to spend time figuring out how to do basic stuff, /requiring/ good documentation - which isn’t provided or fragmented over unrelated sources and code.
My point is that with good API design this understanding would flow naturally from the API - instead of documentation.
IMHO, the editor API is far too often C# implemented in a C++ “script” style (i.e. I can’t even call it proper C++ style because there are excellent examples of extendable UI libraries out there in modern C++ (e.g.: Qt)).
Performance issues aren’t the argument here either. Calling the method on the base class EditorTool for context swaps that happen at most (!) once per frame are not going to matter, even if virtual. Providing context in the form of two references to instances, isn’t either.
Not to mention that this leads to everyone reinventing the wheel in slightly different ways. (Compare the source code per example of Bolt and OdinInspector)
And now for the truly tragic part: Initially it looked like the API design WAS going to be “better” C# design style. I.e. EditorTool would have OnActivate() and OnDeactivate(), per this post .
I would be very interested to learn why this decision was made, @kaarrrllll
I feel that Unity at this point has matured/aged enough that we should start holding new API to a higher standard. I can understand why old API isn’t upgraded, but we should at least strive to uphold new API to a better standard. And if that API can’t be written as such, that it’s made clear that the underlying issues need addressing.
Related post: