Search Unity

  1. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  2. Scriptable Render Pipeline improvements, Texture Mipmap Streaming, and more! Check out what we have in store for you in the 2018.2 Beta.
    Dismiss Notice
  3. If you couldn't join the live stream, take a peek at what you missed.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  5. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  6. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

(Solved, but unhappy)ScriptableObject.Awake never execute

Discussion in 'Documentation' started by PJRM, Aug 16, 2017.

  1. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    264
    Hello!
    On ScriptableObject.Awake documentation, It says:
    But the problem is that this function is never called! I'm using 2017.1.
    Is there something wrong?
    None of these work:
    Code (CSharp):
    1. void Awake() {
    2.    Debug.Log("Test!");
    3. }
    Code (CSharp):
    1. private void Awake() {
    2.    Debug.Log("Test!");
    3. }
    Code (CSharp):
    1. public void Awake() {
    2.    Debug.Log("Test!");
    3. }
    Code (CSharp):
    1. protected void Awake() {
    2.    Debug.Log("Test!");
    3. }
    So, someone manage to make it work??? I need this soooo badly to avoid making any "jerry-rig" code.
     
    Deeeds, AdmiralThrawn and LouisHong like this.
  2. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    264
    Oh well... I created a report: https://fogbugz.unity3d.com/default.asp?943003_3rnv3sufsjhjjeff

    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.
     
  3. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    264
    So. I got an answer from Unity about the report.
    I have to test it and IMHO, Devs: Take a kind look at this!

    The scripts are simple:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace Game.Test {
    4.    public class Test : MonoBehaviour {
    5.       public TestSO testing;
    6.    }
    7. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace Game.Test {
    4.    public class TestSO : ScriptableObject {
    5.       protected virtual void Awake() { }
    6.    }
    7. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace Game.Test {
    4.    [CreateAssetMenu (menuName = "Test/Testing ScriptableObject")]
    5.    public class TestChildSO : TestSO {
    6.       protected override void Awake () {
    7.          base.Awake ();
    8.          Debug.Log("Testing");
    9.       }
    10.    }
    11. }
    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...
    Since the first test didn't work I add some code to the Test class:
    Code (CSharp):
    1. private void Awake() {
    2.    testing = (TestSO) ScriptableObject.CreateInstance(typeof(TestChildSO));
    3. }
    And it work!
    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!
     
    Deeeds and kobyle like this.
  4. Wdarkfenix

    Wdarkfenix

    Joined:
    Feb 3, 2013
    Posts:
    4
    Thank you for posting this. It explains a lot and I agree with you, it should be called OnCreate() Instead. Maybe is some inheritance shenanigans.
     
    Deeeds, AdmiralThrawn and PJRM like this.
  5. wintermute83

    wintermute83

    Joined:
    Mar 9, 2015
    Posts:
    19
    Totally agree.
    Thanks for posting.
     
    PJRM likes this.
  6. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    288
    Just discovered this. Wasted some time on it.
     
    PJRM likes this.
  7. cdytoby

    cdytoby

    Joined:
    Nov 19, 2014
    Posts:
    106
    I just have this problem and found this post. Thanks for saving my time.
     
  8. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    30
    try OnEnable Instead ?
     
  9. cdytoby

    cdytoby

    Joined:
    Nov 19, 2014
    Posts:
    106
    OnEnable will be executed when Editor is not in playmode and an instance is assigned to a gameobject's script's parameter. So, this is not good.
     
  10. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    5,744
    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?
     
  11. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    30
    Hi all, scriptable call Awake when my game open on android device , but when Editor play, it's not trigger ??? im so confuse -_-
     
  12. cdytoby

    cdytoby

    Joined:
    Nov 19, 2014
    Posts:
    106
    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?
     
  13. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    30
    yes, it will load all ref from scriptable object to memory
     
  14. vimutti

    vimutti

    Joined:
    Nov 22, 2017
    Posts:
    5
    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.
     
  15. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    264
    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.
     
  16. wintermute83

    wintermute83

    Joined:
    Mar 9, 2015
    Posts:
    19
    This is my workaround.

    1. Create a derived class from scriptable object with functions for the callbacks ( OnAwake() ), I called it monoscriptableObject.
    2. Create a scriptable object with a list that references the new monoscriptableObjects that need normal monobehaviours callbacks, I called it MonoCallBacks.
    3. 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() }}
    4. Have an instance in your scene of MonoCallBacks.

    It's a bit of a hassle, but works for me.
     
    Last edited: Jun 12, 2018