Why do I have to explicitly DontDestroyOnLoad() my inner variables?

I want my `Player` object to persist between levels, so I call this in the `Start()`

DontDestroyOnLoad(gameObject);

And while this worked, this started acting very very strange after the next level loaded. It turns out lots of things the player instance depended on were being destroyed. I ended up with this to make it right.

DontDestroyOnLoad(gameObject);
DontDestroyOnLoad(bullet);
DontDestroyOnLoad(explosion);
DontDestroyOnLoad(renderer.material);

for (var skill : Skill in skillComponents) {
  DontDestroyOnLoad(skill);
}

So I had to mark all my prefab variables to not be destroyed as well as my material.

My question in why? Is there a rule of thumb about what should be marked dont destroy and what should not? The prefabs and objects stored in internal variables I almost get the need, but why on earth would my material need to be explicitly retained?

From the behavior you describe it seems that your "variables" are actually game objects that are simply assigned to your script. DontDestroyOnLoad(...) has an effect for the game object on which it is called including all the components that are attached to the game object.

However, any other game objects references from that script are not automatically kept. If you need to mark all components of a single game object with DontDestroyOnLoad(...), that would be considered a bug, though.