I have a bunch of “manager” objects. They have dependencies on each other. This poses a problem when I instantiate each object as a prefab as one object or another will inevitably not exist and so references can’t be set/initiation code can’t be run etc in awake or start for at least some such object. Is there an idiomatic solution to this issue? Should I put the “awake” and “start” stuff into non Unity functions and then just call them in my scene startup code? For example maybe every object has a “set refs” function and then an “init” function and the scene spawn code just instantiates each object, calls set refs on each object, and then init on each? Or am I making it too complicated and should I just make the scene have all these objects already in it so I don’t have to deal?
#Circular dependencies with instantiating “manager” prefabs
1 messages · Page 1 of 1 (latest)
Relative to referencing, what I normally do with Unity objects overall is to assign references to this object's components in Awake and others in Start.
Doesn’t that not work if you instantiate prefabs because each instantiate calls both awake and start, so you still get start being called on one object before the next is even created - right?
Start isn't called right away iirc
Basically, everything goes in Start unless you're certain it exists. And these certain items would likely only be component instances on this object. For example, you'd assign the player's rigid body component in Awake (if not done so from the inspector, for whatever reasons) but would assign a reference to the manager in Start.
do all your managers derive from MonoBehaviour? if so, do they need to do that?
Managers generally shouldnt need all the lifecycle stuff that comes with MonoBehaviour. but it obviously depends on the specifics of that manager itself
Um…. I think they do and the main reason is so I can give them stuff in the inspector but I agree that it’s not necessary…
I’ll have to see how much work it is to modify all this stuff and then how much of a payoff it would be to refactor…
Probably would pay to clean things up in the long run
depending what is in the managers, making some stuff static may make referencing easier
public class MyClass {
public static MyClass CreateInstance() {
return new MyClass();
}
}```
Like in this class, I dont actually need to first locate a specific instance of MyClass to get the static method, I can access it like
```cs
public class SomeComponent : MonoBehaviour {
void Start() {
MyClass foo = MyClass.CreateInstance();
}
}```
there are some caveats to using static, but it typically makes life easier when you just want to do something in a class when you dont really care much about the specific instance of that class
Managers in regards to Unity, often refer to Singleton instances of a Unity Object.
that is true, Singletons are good when its important you interact with a specific instance of the class, which can be helpful but it really depends on what the manager is or what its used for
but you have to actually construct the instance of the class before you can use them
whereas if the whole class was static, like this one, its accessible globally purely by writing InstanceHelper., it doesnt need to be constructed beforehand
public static class InstanceHelper {
public static T LoadAndInstancePrefab<T>(string path) where T : UnityEngine.Object {
T prefab = Resources.Load<T>(path);
return Object.Instantiate(prefab) as T;
}
}```
I kind of avoid static stuff for this purpose just bc it feels very brittle
https://github.com/Hambones82/Rebuild-the-Forest/tree/master/Assets/Scripts/Managers. here it’s all these things… most of them
They end up using a bunch of Unity things so I just make one GO per manager
I don't believe he's attempting to make a helper/utility tool but rather some manager that simply distributes easy to access referencing amongst several objects.
I had them just sitting in a scene but I want to make it more controllable so I’m moving to programmatic scene loading
But then I ran into the circular refs problem where it was sort of worked out before
And the cleanest solution seemed to just be avoid awake and start and have some special bootstrapper gameobject load all the managers, set refs, and call Init()
I was just wondering what other people do
There may be other purposes though but generally in game development with Unity, folks use managers to consolidate tedious referencing - anti pattern in normal programming (more room for error with dependency on a single object etc)
That’s kind of how I’m using them
One type of monobehqvior just references its own manager if anything
And then the managers can talk to each other if needed
So that everything isn’t maximally spaghetti
But it seems no matter what I do it’s just a game of hide the spaghetti
And the managers also control spawning and killing and other stuff like that
In general id say those look good, but perhaps if the problem youve got is that making sure theyre actually constructed correctly with the right references (this is also an issue ive faced before), a solution I have found to help is like this
void MakeInstance() {
MyClass foo = InstanceHelper.LoadAndInstancePrefab<MyClass>(pathToResource);
// foo.Awake() will be called immediately upon the prefab being loaded
// data can be set in foo, this is called before foo.Start(), that will be called after MakeInstance() is finished
foo.someNumber = 1f;
}```In that method, you could go and create 20 different managers, in any order you want, and make sure they all actually have the correct references
ive had trouble before where I created two classes and then its pain when their Start() almost have to be called at the same time
I'm guessing they've got several managers already in the scene and that they're discovering issues with race conditions.
yeah, it seems like it, its a tricky thing to fix
That’s basically it. I added more and more stuff and each thing I added was added in a way that made it work. But now that I’m trying to change that whole structure it seems it’s a bit brittle.
Just don't access anything not attached to this object in Awake. Meaning you can assign references to its components (including this instance for managers) and would configure your other members that rely on instances not attached to this object in Start etc
Alright I’ll try and do that
the biggest help would be to ensure that you know X class will need Y, design your code to guarantee Y has to exist first, make sure that certainty is there before you are allowed to construct X
for that id just do a condition like this, by default it will never be allowed to construct the manager
bool canCreate = false;
// determine the conditions needed
// before canCreate can be true
if(canCreate) {
// safe to construct the manager now
}```