Search Unity

Where has GameObjectEntity gone? =<

Discussion in 'Entity Component System' started by Cynicat, Feb 17, 2020.

  1. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    It's been a bit since I used ECS, I really liked writing my code as systems with gameobjects, I like writing ECS style, but well... ECS's component system is still a giant pain. Where is GameObjectEntity, that used to be how you get GameObjects to be found by system queries (Entities.ForEach). I tried using Convert and Inject, but that just duplicates things like the renderer so now it renders twice... o_o

    I also noticed in VSCode that the intellisense is totally borked on Entities.ForEach, even when i put a normal component in there it still shows me the properties like it's an array of some kind.I don't know if that's an ECS codegen bug or Resharper breaking somewhere, but that didn't used to happen.

    Kinda sad, cause currently the conversion workflow has no good workflow for handling reference types, communicating with gameobjects, tweaking values at runtime or frankly even previewing values at runtime(you try using the entity debugger to inspect a large scene...). etc... Hybrid was nice because i could code in systems, then when i had my behavior how i wanted i could just switch over to using pure ECS components on the stuff that made sense. Without that, trying to actually code gameplay is like 10x harder and I can't find a good way to make hybrid objects anymore. =/
     
  2. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    982
    What entities version are you using? I haven't upgraded yet as we're also heavily dependent on GameObjectEntity. We'll have to make a lot of changes to be able to use conversion workflow. It's not very suitable to use on an existing big project using lots of GameObject/MonoBehaviour references.
     
  3. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    It still exists in 0.6 but it's now hidden. It can no longer be added from the context menu - you have to navigate to the entities folder and drag the script onto a game object.

    I don't really get your aversion to conversion after a year of complaining about it. You can make it behave exactly like GameObjectEntity with about 50 lines of code and it's totally fine for huge projects.
     
    Last edited: Feb 18, 2020
    NotaNaN and Enzi like this.
  4. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    982
    It's slow. I'd have to do a major refactor to make it work.
     
  5. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    Actually not much, the alternatives here are AddHybridComponent, AddComponentObject and Convert And Inject, one of those will do the work,
     
    Enzi likes this.
  6. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    Could you point me in the direction of those 50 lines of code? I'd like to use ECS some more and i can't find any docs on hybrid workflows that are up to date. What am i missing?
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    Cynicat likes this.
  8. davenirline

    davenirline

    Joined:
    Jul 7, 2010
    Posts:
    982
    You don't know slow it is. It literally freezes the game for a while whenever a prefab is instantiated. Our character GameObjects have lots of components in them that its not reasonable to rewrite them to AddHybridComponent or AddComponentObject. Not included here is the regression tests involved to make sure that the game still works.
     
  9. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    855
    cant you pool them if this is the case? im curious what your exact use is with GameObjectEntity/proxy that you cannot achieve with conversion
     
  10. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Performance is fine, no idea what you are doing wrong.

    We convert a lot of legacy prefabs during world generation without issue.
    Are you not caching your prefabs (and pooling injected) conversions?
    You only need to convert every prefab once.

    Creating a new world for every conversion is super slow. Do them all in the same world for conversion then cache them as entity prefabs (and pool the game object parts.)
     
  11. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    Thanks for the link but... Does that really mean the current workflow for hybrid involves having a bunch of boilerplate for every component i write and having to manually flag every single default component i don't want destroyed by the conversion system. o_o. If so, that is a hellish workflow, seriously wtf?
     
  12. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    If you just want class-type components, you can use a class type IComponentData. If you really want to use ECS with MonoBehaviours for everything, you can specify an interface for the MonoBehaviours and write a GameObjectConversionSystem that performs all the AddHybridComponent calls for everything.
     
  13. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    Hmm, well that's horribly disappointing. mean's i probably won't be using ECS for anything serious any time soon... The article is good though, good refresher on the current state of things, really thanks for the link =3
     
  14. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    You need only need to add ConvertToEntity to the root GameObject, not every single GameObject. It convert the entire hierarchy.
     
  15. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    That's not what i'm talking about. I'm referencing the logic required to link a gameobject and entity in a manner similar to how the GameObjectEntity component works. Currently it looks like you need complex conversion systems in order to link the two in the same way, using the new conversion system.
     
    davenirline likes this.
  16. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    GameObjectConversionSystems are quite simple to write and you can use them to convert, inject, or migrate any combination of GameObject components including built-in ones. I'm pretty sure this is what @tertle meant by "50 lines of code". I have an example system written here: https://github.com/Dreaming381/Lati...hysics/Authoring/CollisionConversionSystem.cs

    Also, is there a reason why class IComponentData doesn't meet your needs for most components?
     
    Sarkahn likes this.
  17. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    Yes, as I explained in my original post, IComponentData isn't editable at runtime, meaning if you want to tweak how fast your characters moves for example, you have to essentially guess, startup game (wait 20-30 seconds for burst to compile), realize it's off, stop the game, guess again, start up the game (wait 20-30 seconds for burst to compile), play and realize that's also wrong, repeat. It's not really feasible for tweaking gameplay. Also ECS is missing the wide majority of gameplay features at the moment. so yeah, it slows things down a ton compared the just tweaking values at runtime. Also, browsing and figuring out a complex scene in the entity debugger is hell. So i generally start with gameobjects and migrate stuff over when i need to for performance reasons (GameObjectEntity workflow). Which apparently cannot be done anymore and it kills a lot of the workflow. Manually writing conversion systems for every single component i make isn't exactly going to work well workflow wise. All i want is to be able to write my code in a System query style like i could before with GameObjectEntity, it looks like that's not possible anymore. =<
     
  18. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    It is with LiveLink.

    You don't have to do this. You just have to write a GameObjectConversionSystem that iterates over Transforms, queries the GameObject for all things that aren't IConvertGameObjectToEntity or your blacklist of Unity components you don't want duplicates of, and then call AddHybridComponent on whatever components remain. You don't even have to write reflection code to do it.
     
  19. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    LiveLink only works with full subscenes. Meaning pure entities only, which is currently missing a huge amount of features and documentation. =/

    Hmm, i didn't think about that approach, i was trying to do Entities.ForEach(MonoBehaviour behaviour) and was getting nothing, that's my bad, that's a really obvious solution in hindsight. One slight problem i'm having is that it's spitting a bunch of random errors when i try to add hybrid components. Stuff like index out of range exceptions and such. But i'll see if i can get some time to try to get this working. Thanks for the tip! =3
     
  20. SamOld

    SamOld

    Joined:
    Aug 17, 2018
    Posts:
    333
    The post I just made here might be an example of something that's become hard or impossible without GameObjectEntity, although hopefully there will turn out to be a good way to deal with it. It used to be easy but now it's not obvious how to solve my problem.
     
    Cynicat likes this.
  21. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    A couple of people have told me similar things about hybrid components. I haven't had much time to play with them personally because I have been too busy with a bizarre Burst write performance issue.

    I suggest making bug reports and posting case numbers on these forums regarding the issues you are having.
     
  22. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    760
    Sorry to bug you guys, but I've been stuck trying to get particles to work in ECS for quite a while.

    TLDR - Is there some sort of project, global setting, system ordering, or additional setup required for AddHybridComponent to work?



    I'm able to get particle systems to spawn in an object pool on demand by calling a singleton function from a main-thread system. This is fine for explosions and similar effects.

    However, I also need to attach certain particle systems to moving entities, and this is where I think AddHybridComponent comes in.

    ...........METHOD 1.........
    As an example of using AddHybridComponent(), I have an empty game object (Foobar) and I want to attach a particle system to it.

    upload_2020-7-8_23-16-45.png


    particle_prefab is a simple prefab that has a single ParticleSystem component. I attached ConvertToEntity.cs to Foobar, which results in 2 entities corresponding to Foobar and particle_prefab that can be seen in the Entity Debugger at runtime.

    If GameObjectConversionSystem works the way I think it does, I should be able to add the following system to the project so that for every particle system, a corresponding game object will be created and "tethered" to the entity.

    Code (CSharp):
    1. public class ParticleConversionSystem : GameObjectConversionSystem
    2. {
    3.     protected override void OnUpdate()
    4.     {
    5.         Entities.ForEach((UnityEngine.ParticleSystem particleSystem) => {
    6.             AddHybridComponent(particleSystem);
    7.         });
    8.         Entities.ForEach((UnityEngine.ParticleSystemRenderer particleSystemRenderer) => {
    9.             AddHybridComponent(particleSystemRenderer);
    10.         });
    11.     }
    12. }
    When I tested this in the ECSSamples/StressTests/HybridComponent class it worked perfectly (which is pretty damn cool), however, when I try to do the exact same thing in my project, neither Entities.ForEach() query fetches any results, so AddHybridComponent() is never called. In my project, the particles disappear during game-play.

    ----------------------------------------------------------------

    ...........METHOD 2.........
    Another approach that I tried was to place the following script onto the Foobar object, much like 5argon did on gametorrahod with his Ship script.

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3.  
    4. public class ParticleConverter : MonoBehaviour, IConvertGameObjectToEntity
    5. {
    6.     public ParticleSystem particleSystemCompanion;
    7.     public ParticleSystemRenderer particleSystemRendererCompanion;
    8.  
    9.     public void Convert(Entity entity, EntityManager entityManager, GameObjectConversionSystem conversionSystem)
    10.     {
    11.         conversionSystem.AddHybridComponent(particleSystemCompanion);
    12.         conversionSystem.AddHybridComponent(particleSystemRendererCompanion);
    13.     }
    14. }
    upload_2020-7-8_23-25-45.png

    In my game, by using the debugger, I can tell that the AddHybridComponent() function gets called and there are no errors, but when the game runs, the particles do not appear on screen. If I remove ConvertToEntity.cs, the particles show up just fine, so the particle system itself is working and valid. This tells me that the problem is somehow related to the conversion.

    What's really got me scratching my head is that if I copy the exact same Foobar+particle_prefab to ECSSamples/StressTests/HybridComponent using ConvertToEntity.cs and the exact same ParticleConverter.cs and place it in front of the camera, the particles show up just fine!

    I upgraded ECSSamples to version 0.5.2 build 4 so it matched my project, but that didn't make a difference.

    How can both methods work just fine in the ECSSamples project, but not my game? Is there some global or project setting I'm missing?
     
    NotaNaN likes this.
  23. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    760
    Well... I fixed it.

    I spent days trying to figure out why I couldn't get hybrid components to work (mistakenly thinking it was a problem with my code). Yesterday I spent half of the day comparing my project settings and packages with settings and packages on other projects where hybrid components worked. I finally gave up and spent the second half of the day copying all my assets and code to a fresh new project. Now it works fine. Yay... that was so much fun.
     
    CookieStealer2 and NotaNaN like this.