I know a thing or two about Unity at this point, but I've still lots of subjective, best practice questions, Such as: How do you decide what values are obtained via Start/Awake initialization, and which values are explicitly serialized into the scene? In my current project, game objects and behaviors reference each other in a complex graph. Initially, I did this on Start(), programmatically, with lots of raycasts and GetComponent<>() and such. Now though, I just declared stuff public (violating encapsulation?), to simply serialize this information to the scene once generated by an Editor script... Which is more correct? Should my methodology be that anything that can be serialized should be serialized? Or is it better to write more initialization code which conveys some explanation why the values are what they are?
You're right that this is subjective. You can load your initialization data from literally anywhere. So in my mind, asking about what method you should use is not answerable by anyone other than yourself.
So regarding how you might make that decision, there are a few things to consider.
You mentioned encapsulation. I think this is not a concept that should be applied to initialization. The thing about configuring the system is that you are doing the part of programming that can't be abstracted in the academically ideal, OO-software way of doing things. Whether you're embedding it inside a dedicated unity script, reading an external text file, or designing some sort of convoluted dependency injection container, it's important to remember what you're trying to accomplish. That something is: the ugly part of the system. The coupling, the dependencies, the code that ought not be within a well-designed class. You need some of that code to make a working system of any type, especially games. But it probably won't be pristine under any circumstances.
Serializability: should you be able to move this data outside the code. I would contend that yes, you should. Many reasons. However, as a stop-gap, implementing the data inside a single unity script is not a bad tactic, as long as you can easily update it and/or transition away from it.
Explanation: should you have to describe the configuration as you write it. Ideally, no, because configuration data ought not be too complicated to speak for itself. Is that the case? Perhaps you should reconsider what is configurable and what is not. If the configuration is susceptible to error, then those errors ought to be caught by the thing loading the configuration. So that might be a better place to explain the cause of the errors. Or to efficiently report errors back to the configuration author, to inform them of their mistake.
- What unity callback should run it. I am not a unity expert, but I would doubt that there is an objectively correct answer to this. My intuition is that it does not matter. You should design your unity app to run some sort of startup logic that loads the data, and from there bootstrap itself into a system that runs the game using that data without worrying where it came from. In other words, show a main loading screen that figures it out. Then transition out of that loading screen into your actual game.