Technically, yeah, there’s always a way. But in practice, in the general sense it can get really hairy.
Also, in the particular case of adding lots of GameObjects, I know they’re not linear: last I checked, adding 1000 GameObjects is WAY more than 10x slower than adding 100 Gameobjects, I presume due to inefficiencies in newly-added stuff, not sure/ No way to tell with a closed-source engine like Unity.
Trying to tie into system timers and judge how long things have taken so far will get you a certain distance, but it might break down on certain platforms and not be reliable. plus the timing calculations can get really difficult to judge and tune.
Another dynamic way to do it is to be happy accepting an occasional frame drop, then start by doing 1 object, yield, 2 objects, yield, 3 objects, etc and steadily building that loop count number up. All the while you do that you are monitoring framerate (in code) and the moment it drops below your acceptable limit you knock a few numbers off that loop count value and don’t increment it again for a short while.
Obviously you’d never let the count go below 1 otherwise your subtask would stall out. And yet it COULD go as low as 1 on a crummy system, so you have to be willing to accept the worst possible loading time.
It’s not pretty. There’s a reason we hide behind loading screens.
NOTE: you can always do stuff on another thread… UNLESS it needs to transact with the Unity engine, which obviously you do in this case, and in almost any non-trivial case of Unity engineering.