Tomer Godinger
Tomer Godinger

Reputation: 380

Awake() for Prefab Without Instantiation

I have a script that accepts a prefab from which it instantiates objects later.

That prefab has some static data in one of its components that I wish to read before instantiating anything, for which I need to get the component, naturally with GetComponent(). Later on that data is read by instances many times, so I don't want to use GetComponent() all the time because I understand it's a rather heavy operation. So naturally, like always, I keep a variable that holds this component and initialize that variable in the Awake() function.

Problem is, the Awake() function isn't called for the prefab itself, but only for the instances I later create with Instantiate().

In other words, ideally I want to do this:

void Awake()
{
    imageSelector = GetComponent<ImageSelector>();
}

public int MaxValue => imageSelector.Count;

But in order for it to work for the prefab itself before instantiation I need to do this:

public int MaxValue => GetComponent<ImageSelector>().Count;

Of course, I can make singleton-like read access where I check if I had already saved the component and fetch and save it if I hadn't, but that's not as nice and it seems reasonable to me that there would be some initialization process I can hook into to do this.

So how do I initialize things for an uninstantiated prefab?

A few other workarounds also come to mind, none of which I particularly like, but I'll use one of them if necessary - still, I'd like to know if there is a clean way to do this.

Thanks in advance.

Upvotes: 2

Views: 2011

Answers (3)

Andrew
Andrew

Reputation: 119

ISerializationCallbackReceiver.OnAfterDeserialize() can be used as a replacement of Awake() for prefabs. It is used like this:

public class AnyCustomComponent : MonoBehaviour, ISerializationCallbackReceiver
{
    public AnySerializedData serializedData;

    private AnyInitializedData initializedData;

    public void OnBeforeSerialize() { }

    public void OnAfterDeserialize()
    {
        initializedData = serializedData.Init();
    }
}

One remark is that this callback will happen not only at the start of the game but also during editing in editor but for most cases it shouldn't really be a problem I guess.

Upvotes: 0

rustyBucketBay
rustyBucketBay

Reputation: 4551

I had some kind of similar problem trying to initialize prefab settings before they where instantiated. It was hard to me to understand as I expected o more clean way to do this, but seems to be the natural way in Unity. Comming from c++, c# or oop in general, it is likely to be used to the setting of the components like in a class constructor. The conclusion I obtained isthat from the programaticall point of view, Unity does not quite come to that operational approach. You can use of course c# normal classes with their constructors etc(not inheriting from monobehaviour) but if you're up to use the Unity classes and tools, you should go through the from the programaticall point of view awkward way of setting classes in Unity, which on the other hand is so operative. So I think that the normal way to set things is via the constructor of the monobehaviour classes, this is the Awake() (or the start() maybe), before jumping into more sophysticated that can be scriptable objects, or .json/.xml readers, that are not trivial to work out unless you have advanced c# and unity knowledge.

Hope that helps

Upvotes: 0

You can't

Prefabs do not have MonoBehaviour methods called on them because they haven't been--and will never be--initialized.

Note that you can just assign the property yourself in the inspector and not bother with the Awake call at all.

Upvotes: 2

Related Questions