Search Unity

Question using Monobehaviour objects in ECS World

Discussion in 'Entity Component System' started by Patrick-Cho, Mar 18, 2023.

  1. Patrick-Cho

    Patrick-Cho

    Joined:
    Jun 6, 2017
    Posts:
    8
    Hi there was something odd while prototyping my dots project.
    (i'm using Entities [1.0.0-pre.44] currently)

    on editor environment, entities with particle systems worked fine
    in the other hand on android builds, the position of particle system did not change.
    it just stuck on (0, 0, 0)

    it took me several weeks to find out that i have to update it manually.
    i know that editor could be quite different from build environment.
    but i couldn't find any information about it(maybe lack of my searching skill)

    get to the point i'm using this code to update the position of particles.
    Code (CSharp):
    1. Entities.ForEach((ParticleSystem particleSystem, in WorldTransform worldTransform) =>
    2. {
    3.      if (particleSystem != null)
    4.          particleSystem.transform.position = worldTransform.Position;
    5. }).WithoutBurst().Run();
    6.  
    my question is. is this the right way to update my particle systems?

    and i tried other Monobehaviours that i made for testing
    Code (CSharp):
    1. Entities.ForEach((TestComponent testComp, in WorldTransform worldTransform) =>
    2. {
    3.     ...
    4. }).WithoutBurst().Run();
    but didn't work. what's the difference between ParticleSystem and others?
    how can i get to use my custom Monobehaviours on Jobs like the first code?

    it's just so confusing @0@

    thank you for your time :D
     
  2. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Are you using baking or GameObject conversion?
    If baking, you get the transform updates for free via CompanionLink and CompanionGameObjectUpdateTransformSystem. All you need do is add the particleSystem.
    Code (CSharp):
    1. public class ParticleSystemAuthor : MonoBehaviour {
    2.     class Baker : Baker<ParticleSystemAuthor> {
    3.         public override void Bake(ParticleSystemAuthor authoring)
    4.         {
    5.             AddComponentObject<ParticleSystem>(authoring.GetComponent<ParticleSystem>());
    6.             AddComponentObject<ParticleSystemRenderer>(authoring.GetComponent<ParticleSystemRenderer>());
    7.         }
    8.     }
    9. }
    If you're doing your own GameObject conversion, then make the transform system generic. I.e. Make your own CopyTransformToGameObjectSystem and use Transform instead of ParticleSystem because ParticleSystem has nothing to do with a gameObjects position. You just need to add the Transform component to the Entity via AddComponentObject.
    Code (CSharp):
    1. Entities.ForEach((Transform transform, in WorldTransform worldTransform) =>
    2. {
    3.     transform.position = worldTransform.Position;
    4. }).WithoutBurst().Run();
    If you want the more complex jobified version, just look at CompanionGameObjectUpdateTransformSystem and replicate that. Or ideally, just add the necessary components in your conversion so your entities use that system too.

    Having said all that, I see no reason your existing code wouldn't work. Have you debugged that the relevant line is actually getting executed and the values are valid?
     
    DAcKey likes this.
  3. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    I assume your test component is a managed component (class).
    If so you code should work in the same way as for particules.

    What I generally do is I store a prefab game object on a class component and use that to spawn the game object at runtime.
    That way I keep track of the link between the go and the entity in case one of them gets destroyed. And I only have one transform to sync.
    Then from system I can access the Monobehavior through the game object or make another managed component with the Monobehavior I want to work with.

    See
    for walkthrough
     
    Patrick-Cho likes this.
  4. Patrick-Cho

    Patrick-Cho

    Joined:
    Jun 6, 2017
    Posts:
    8
    Thank you for your reply!
    yes I'm using Baker, oh and i tried AddComponentObject<ParticleSystem>(...) and got error below.

    InvalidOperationException: Baking error: Attempt to add duplicate component UnityEngine.ParticleSystem for Baker SpaceShip.ParticleSystemAuthorMono+Baker with authoring component SpaceShip.ParticleSystemAuthorMono. Previous component added by Baker Unity.Rendering.ParticleSystemCompanionBaker
    ....


    I think this means the ParticleSystem is already added to entity somewhere atomatically(and i did not add it manually).
    but not updating the transform via CompanionGameObjectUpdateTransformSystem.

    And I tried adding other monobehaviours and found out, only adding ParticleSystem causing the problem.
    AddComponentObject<Transform>(...);
    AddComponentObject<CustomBehaviour>(...);
    ↑ these worked fine(But Position not updating)

    Oh and real furious point is...
    It works perfectly on Mono build(even with no AddComponentObject<ParticleSystem>(...), )
    but not on IL2CPP build...

    To summarize
    1. Error on AddComponentObject<ParticleSystem>(...)
    2. No Error found on AddComponentObject<Other Behaviours so far>(...)
    3. Adding AddComponentObject<Other Behaviours>(...). CompanionLink is not working(Position not Updating)
    4. On Mono Build Particle System Position is updated. Even there is no AddComponentObject.
    5. On IL2CPP Build Particle System Position is not updated..

    do you have any clue?
     
  5. Patrick-Cho

    Patrick-Cho

    Joined:
    Jun 6, 2017
    Posts:
    8
    Thank you these method was something i was looking for too!
     
  6. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Ah, I see. It's part of the entities.graphics package which I'm not using. It has a built in baker for ParticleSystem so yes, no need to create your own.
    In that case I'm not sure. I can't test on mine cos graphics package throws errors out of the box.
    Edit: Get rid of any of the previous code/suggestions I posted. They'll only conflict with the graphics package and companion mechanism you're using.

    I'd create an empty project with a Sprite GameObject and a ParticleSystem GameObject in a subscene. Place them both off center and build it and see if Sprite shows up but Particles don't, then it's a graphics package or build issue. Possibly something is getting code stripped. Could try disabling managed code stripping and see if that resolves it.

    Alternatively use the prefab option as Wayne suggested which is what I use. That way you're not at the mercy of Unity's frequently changing hybrid mechanics.
     
    Patrick-Cho likes this.