If you use Microsoft’s DI Extension it gets even easier.
But don't use dependency injection. Unity's Scene/Prefab load/instantiation is already a form of DI. Using another causes issues with juggling multiple lifecycles.
You also lose the ability for Unity to prefetch assets because Unity can't inspect the dependency graph if it's not done through the asset system. Instead you hit situations where you're loading several objects and running DI code over several frames when unity could have loaded everything at once.
I am not a game dev, more app/audio/web, but our app uses Unity for the 3D and interactive video lesson playback parts and recently I’ve been refactoring the video part, which is a perfect candidate for building out with unit and integration tests. It took a lot of digging to work out how to use the Unity unit test stuff effectively as there are really just a few toy examples out there, same with async/await (and the unit test runner still cannot handle async/await in tests!).
I guess maybe it’s a culture thing to some extent, unit testing maybe isn’t as prevalent in games for whatever reason? Once I worked out, as you say, that I could move most of the logic into plain C# classes and test them much the same way I would any old business logic, things became much easier to deal with.
I did think about using DI but in the end found that passing GameObjects in via the IDE and public members as the other comment says sufficed for anything which is a GameObject, and the other (plain class) dependencies I am new’ing up in a top level Manager class and passing down through the constructor, and using NSubstitute to pass in mocks in the unit tests.
I might write up my experience/findings some time when the work is complete.
On the whole, I do think Unity is great, I’ve seen how fast we were able to build out a great looking experience and it’s pretty easy to figure out. C# is a really nice language too. Just a shame that more “modern” dev practices are not actively promoted, and parts like async/await and unit testing seem to be left half-finished.
One thing I noticed from just skimming the tutorials is there is a lot of Unity editor specific creation of stuff. How much of that is the actual game programming? Maybe web dev is headed in that direction if we ever eventually map Figma to components, where you kind of define it via a GUI. Seeing that felt a little off putting since I’m used to working with a tight scaffold that’s mostly code.
Godot looked less GUI intensive so I was thinking about digging into that instead.
I guess another way to pose this question is, do I need to get over this and accept this is how games are made?
I kind of wrote about "keeping it all in code" and why it isn't desirable in the second installment: https://blog.eyas.sh/2020/10/unity-for-engineers-pt2-six-pra...
But once you get the placement / connection / injection right, you'll still be spending the bulk of your non-testing development time in the code editor.
The second installment (already published) talks about some of these best practices, but it doesn't quite dig into architecture just yet.