Search Unity

"All ComponentType must be known at compile time"

Discussion in 'Entity Component System' started by BackgroundMover, Oct 24, 2019.

  1. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    224
    When trying to load up some mod code that uses ECS, I'm running into this error in the console:
    The message seems pretty clear and final. Is it simply a trait of ECS that you cannot load up unknown Components at runtime? I'm using the excellent Umod off the asset store, so if its a matter of simply loading things a certain way, I'd be keen to hear it.

    Also, is there some example of using generic components and [RegisterGenericComponentType]?
     
  2. rsodre

    rsodre

    Joined:
    May 9, 2012
    Posts:
    229
  3. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    224
    Thanks for pointing me to the example. I'm pretty new to generics but it seems like I can't solve my problem with generics. Has anyone been able to get an IComponentData to load at runtime from a DLL? I believe thats how UMod works under the hood.
     
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    I believe it /might/ be possible if you stop automatic world creation, load your DLLs then setup the world.

    Basically you have to load all your components before TypeManager is initialized (only happens once, not per world).

    I have not tried this though and this is just from memory looking at TypeManager 3-6 months ago.

    -edit-

    just to elaborate on this as I have a minute while something compiles.

    World creates EntityManager
    EntityManager calls TypeManager.Initialize

    While TypeManager.Initialize is called from all EntityManagers, it is only executed once per the life of the app so you can't make changes to this after the start.

    TypeManager.Initialize calls a method InitializeAllComponentTypes.

    Within this it loops all assemblies in the current app domain, gets all types that inherit from the Entity base types (IComponentData, ISharedComponentData,IBufferElementData) and basically builds a couple of different types of fixed array for fast access in various circumstances.

    So if you can load your custom types into the AppDomain before this happens, it should work I think.

    I am unfamiliar with Umod and how it works, so can't help you there.
     
    Last edited: Oct 25, 2019
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,270
    Hopefully with the next package release the automatic world initialization gets refactored such that Unity does not create the first World until after it calls an ICustomBootstrap. I remember seeing some code posted by someone from Unity about how bootstrap code might look a little different in the next update.
     
    florianhanke likes this.
  6. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    224
    @tertle Dude! It worked! This was massive for me, thank you so much. At first I was investigating
    #UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_RUNTIME_WORLD

    to take control of the World -> EntityManager -> TypeManager.Initialize process as you said, but I realized I can get in early with the attribute
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]

    over a public static void function which calls my mod loading code. Thank you so much for sharing your knowledge, this could have set me back weeks or worse.
     
  7. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    224
    As an update to this, it seems like a class TypeDependencyCache is making a call from its static constructor (!) to TypeManager.Initialize(), at least in the Editor. It seems like the proper fix for this is to call TypeManager.AddNewComponentTypes(). Its editor-only, but so is TypeDependencyCache.

    Edit: I went with #UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_RUNTIME_WORLD after all, it was much simpler than I was worried about. Trying to get my code to run before the ECS setup was hacky anyway.
     
    Last edited: Mar 4, 2020
    florianhanke likes this.
  8. Zylkowski_a

    Zylkowski_a

    Joined:
    Jul 27, 2019
    Posts:
    157
    I am having similar problem, can you elaborate on using #UNITY_DISABLE_AUTOMATIC_SYSTEM_BOOTSTRAP_RUNTIME_WORLD ?
     
  9. Zec_

    Zec_

    Joined:
    Feb 9, 2017
    Posts:
    148
    I was playing around with dynamically compiled/loaded code a few weeks ago. This is a similar topic, so I just thought I'd chime in what I learned. We were trying to implement scripted gameplay systems that we could recompile and reload during playtime. We actually had this working back in Entities 0.2, but couldn't get it working in the newer versions.

    I think I remember managing to find some static method to register my component types with in TypeManager. I think it was the previously mentioned AddNewComponentTypes, but I also have some vague memories of fiddling around with internal APIs via reflection to make the last parts work (can't remember, sorry). We also managed to get burst to pick up the assemblies so that they were properly burst-compiled. Our systems+jobs that used the old IJobForEach worked great.

    The main issue that prevented us from continuing with our planned approach was the fact that we couldn't get the code generation/ILPostProcessing for Entities.ForEach to run on assemblies that we compiled/loaded ourselves. Since Entities.ForEach is somewhat of a cornerstone of systems+jobs, we shelved those plans for now.