Since I’m not able to use Awake function on ScriptableObjects, I had to create an Init() function and now I have to call Init() everytime on the Awake gameobject, runing a foreach fr every ScriptableObject attached and I do the same for every other ScriptableObject that it is attached inside my others ScriptableObjects.
Really not a good way to do the coding on this scripts. Bad! Very bad!
I’m open to suggestions, solutions, whatever… This is giving me a nervous tic, everytime I have to call this Init function.
I have to test it and IMHO, Devs: Take a kind look at this!
The first Test I made
The scripts are simple:
using UnityEngine;
namespace Game.Test {
public class Test : MonoBehaviour {
public TestSO testing;
}
}
using UnityEngine;
namespace Game.Test {
public class TestSO : ScriptableObject {
protected virtual void Awake() { }
}
}
using UnityEngine;
namespace Game.Test {
[CreateAssetMenu (menuName = "Test/Testing ScriptableObject")]
public class TestChildSO : TestSO {
protected override void Awake () {
base.Awake ();
Debug.Log("Testing");
}
}
}
Observation: I created the ScriptableObject file on an folder and attached to the slot on the gameObject in inspector.
I thought it required the Awake function on the base class, but when I run, it doesn’t work! So…
The Second Test I made
Since the first test didn’t work I add some code to the Test class:
Conclusion: In my point of view, this method should be renamed to OnCreated. Why is that: Simple, the Awake does not run if a GameObject is on the scene, but only if a script creates the ScriptableObject!
When a Object is Awakening, ( if the ScriptableObject have the same method and the documentation says that it works similar way as MonoBehaviour, ) then the ScriptableObjects must execute Awake too! Otherwise it’s purpose lacks meaning! It is an OnCreated execution! More logic and coherence. Remember: this is my point of view and my argument!
The documentation is incorrect here, it’s an ambiguous and misleading statement.
But for consistency Awake() is plenty clear. Both Mobobehaviors and ScriptableObjects must have an instance alive and running in a scene in order to get their built-in calls. It’s already known how Awake() works - only fired once when the object is instanced - so why bother creating a new built in call that is executed exactly the same?
I decided to load the scriptableObjects asset from Resources. But I don’t know if this single asset contains 1000 different references (gameobjects, sprites, etc), will it affect performance?
I tested it. Look like the editor version is act different from the built version. In editor version, Awake will not be called by created scriptable. But in built version, it will be called. I assume that the built version will re-create all scriptable every time we start game so all Awake will be called.
The main issue here that i wrote about it, is because of the statement on documentation.
Please make sure you ready well my 3rd post , because it explain well. The Awake only run on scriptableobject when created, not loaded. To me this never make sense to be called Awake. On build version, the awake is called because the engine need to create the scriptableobjects to be ready.
It’s a OnCreated method. Not Awake method.
I don’t know how to explain better. I even give example script above to show whether this is true or not! On my Statecontroller i even created a Setup method which i call it everytime i load the script, because i need some settings to be set before update starts.
Create a derived class from scriptable object with functions for the callbacks ( OnAwake() ), I called it monoscriptableObject.
Create a scriptable object with a list that references the new monoscriptableObjects that need normal monobehaviours callbacks, I called it MonoCallBacks.
Create a monobehaviour with a reference to the list in point 2 that calls those functions when their callbacks are called. ie. OnEnable() { foreach mso in list { mso .OnEnableCallBack() }}
Not quite.
I’ve debugged this to death and back because I was wondering the same thing.
There are 3 different cases that will cause a ScriptableObject to call Awake()
1 - When it’s created. (Editor Only)
2 - When a scene which contains an object that references the asset is loaded.
3 - When the asset is first selected in the project window IF Awake() hasn’t already been called. (Editor Only)
Please correct me if I’m wrong, but in all the tests I’ve done, I’ve found this to be the consistent behaviour.