Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

[RuntimeInitializeOnLoadMethod] does not work on serialized generic classes.

Discussion in '2020.1 Beta' started by toomasio, Mar 28, 2020.

  1. toomasio

    toomasio

    Joined:
    Nov 19, 2013
    Posts:
    198
    This works:
    Code (CSharp):
    1. [System.Serializable]
    2.     public class ObjectReference : ScriptableReference<ScriptableObject>
    3.     {
    4.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    5.         static void Test()
    6.         {
    7.             Debug.Log("wooooo");
    8.         }
    9.     }

    But this doesn't. Not sure how hard this would be to get working? It would be easier if we could have a base initializer so we don't have to create inititalizers for every subclass...or create concrete subclasses.

    Code (CSharp):
    1. [System.Serializable]
    2.     public class ScriptableReference<T> where T : ScriptableObject
    3.     {
    4.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
    5.         static void Test()
    6.         {
    7.             Debug.Log("wooooo");
    8.         }
    9.     }
    EDIT: Just realized I have been using this attribute wrong anyways.....it calls even if there is not an instance of the class...and only calls once. not on multiple instances. Darn.
     
    Last edited: Mar 28, 2020
  2. Hyp-X

    Hyp-X

    Joined:
    Jun 24, 2015
    Posts:
    438
    This look strange if you think about it.
    What kind of T type do you want Unity to call this function?
    Unlike C++ templates which instantiated at compile time, C# generics only instantiated at runtime so there's not a good place where the system can decide if a type ScriptableReference<Foo> exists or not.
     
    toomasio likes this.
  3. toomasio

    toomasio

    Joined:
    Nov 19, 2013
    Posts:
    198
    Yeah realized I have been using this wrong. Have to stick to intializing my classes :/ until I can come up with some referencing list system.
     
  4. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    I recently stumbled upon this as well. It is a bummer this is not mentioned in the docs.

    I solved this issue by using only a single
    [RuntimeInitializeOnLoadMethod]
    in a non-generic
    ScriptableObject
    (think of it like a registry) and put its instance under a Resources folder.

    Then for everything else that needs to receive runtime initialization (for example: singleton
    ScriptableObject
    s for project-wide config) I wired them up to the registry instance.

    In the
    [RuntimeInitializeOnLoadMethod]
    , I find the instance of the registry with
    Resources.FindObjectsOfTypeAll<T>()
    . Then I manually invoke a custom
    RuntimeInit
    method on everything that was assigned to the registry instance in the inspector.

    Seems to work well enough and it is pretty flexible.

    If you have Odin, you can even define an interface like this and take in an array in your registry instead of defining a field for every type you have:
    Code (CSharp):
    1.  
    2. public interface IModule
    3. {
    4.     void RuntimeInit();
    5. }
    6.  
    7. // then, in the registry:
    8. [OdinSerialize] private IModule[] modules;
    9.  
     
    Last edited: Sep 23, 2021
    seoyeon222222 likes this.