Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

ECS Advice

Discussion in 'Entity Component System' started by Shabbalaka, Sep 26, 2019.

  1. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Default constructor, without arguments. I'll rename it in answer for better context.
     
    Last edited: Nov 11, 2019
  2. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    I wrote this and from what I gather is the Constructor is basically the thing that "glues" the Class values to the Class and when you create a new Object of that Class the Constructor expects a parameter or a value for those values.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class User
    5. {
    6.  
    7.     private string MyName;
    8.     public int MyAge;
    9.  
    10.     public void SetName(string name)
    11.     {
    12.         //Cant remember the Get:Set Shorthand...
    13.          MyName = name;    
    14.     }
    15.  
    16.     public string GetName()
    17.     {
    18.         return this.MyName;
    19.     }
    20.  
    21.     public void SetName(int age)
    22.     {
    23.             //Cant remember the Get:Set Shorthand...
    24.             MyAge = age;    
    25.     }
    26.  
    27.     public int GetAge()
    28.     {
    29.         return this.MyAge;
    30.     }
    31. }
    32.  
    33.  
    34.  
    35. public class ConstructorExample : MonoBehaviour
    36. {
    37.  
    38.  
    39.     public void Start()
    40.     {
    41.  
    42.         User newUser = new User();
    43.         newUser.SetName("Shabalaka");
    44.  
    45.  
    46.  
    47.         Debug.Log("My Name is " + newUser.GetName());
    48.         Debug.Log("My Name is " + newUser.GetAge());
    49.  
    50.     }
    51.  
    52.  
    53. }
    54.  
    Like Age here defaults to 0 because it has no value and is an int, If i used a string I think it would be null or undefined.

    The MyAge value has to be "set" within a method because they are declared private which means that only this script can access them directly and other scripts will have to go through the "channels" or methods which allow access to them (I think)...

    Protected I think means that these values only exist in this script and cannot be seen by any other.

    Public means I can access these class values from anywhere by going User.MyAge();

    Constant means that they cannot be changed and are a fixed value (Again I might be wrong here)


    returning this.MyAge refers to the instance that was created when calling User NewUser = new User() (Again I think this is correct)
     
  3. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    Its cool you never stop learning and any advice is helpful!! :)

    Can i query this sentence though?
    Where in this struct is a Initilizer ?? I am guessing its,
    public NativeList<Vector3> DeadEnemyPositions; <-- This is what i think is most likely causing this error.
    or
    DeadEnemyPositions.Add(enemyPos.Value);

    Code (CSharp):
    1. private struct EnemyHealthJob : IJobForEachWithEntity<EnemyTagComponent, HealthComponent, EnemyID, Translation>
    2.     {
    3.         public EntityCommandBuffer.Concurrent Ecb;
    4.  
    5.         public NativeList<Vector3> DeadEnemyPositions;
    6.         public void Execute(
    7.             Entity entity,
    8.             int index,
    9.             [ReadOnly] ref EnemyTagComponent enemyTag,
    10.             ref HealthComponent health,
    11.             ref EnemyID id,
    12.             ref Translation enemyPos)
    13.         {
    14.    
    15.             if(health.HP <= 0)
    16.             {
    17.                // Debug.Log("Enemy ID "+ id.id + " is dead.");
    18.                // Debug.Log("Entity index is " + index);
    19.                // Ecb.DestroyEntity(index, entity);
    20.                  DeadEnemyPositions.Add(enemyPos.Value);
    21.                 //EnemyDeathSystem.PlayDeathAnimation(enemyPos.Value); /*<---- OUR LIST OF DEAD ENEMYS INSIDE OUR JOB*/
    22.             }  
    23.               // return DeadEnemyPositions;
    24.         }
    25.     }
    The rest of the code is in OnUpdate which runs on the main thread and not on a background thread which appears to be seperate to the main thread hence why the background thread does not know about EntityManager and is inaccessible to Job,s.

    As you can see how I explained why someone cannot use EntityManager within a Job can you explain to me in very basic terms why I cannot initialize a field in a Struct please. :)

    Many thanks !
     
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    It's field declaration.

    Row 22 from post where you saw initializer error.
    I explained that above. It's compiler limitation.
     
    Last edited: Nov 11, 2019
  5. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    No. You can't use it inside job cause it's reference type, only blittable types allowed, it's Job System requirement. Moreover most part of EM API causing structural changes which not possible outside of main thread (exception is ExclusiveEntityTransaction which allow bock all other acces to EM and do structural changes on thread where job running)
     
  6. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154

    Thank you for your explanation!! :)

    Now I understand that I can only use a Blittable type within a Job which are in basics the primitive types the same way that I cannot use a ParticleSystem within a Component and attach that to an Entity.

    I just read up on here

    https://en.wikipedia.org/wiki/Blittable_types
     
  7. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    Right after a few more days messing with Jobs and stuff I thought I would return with my latest issue.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using Unity.Mathematics;
    6. using Unity.Jobs;
    7. using Unity.Transforms;
    8. using Unity.Collections;
    9.  
    10. [RequireComponent(typeof(EnemyTag))]
    11. public class RotateJobSystem : JobComponentSystem
    12. {
    13.  
    14.     public struct RotateJob : IJobForEachWithEntity<Translation, RotateSpeed, MoveSpeedComponent, Rotation>
    15.     {  
    16.         public float time;
    17.  
    18.         public void Execute(Entity entity, int index, ref Translation position, ref RotateSpeed rotSpeed, ref MoveSpeedComponent msc, ref Rotation rot)
    19.         {
    20.             //THIS MOVES THE ENTITY TO THE RIGHT.
    21.             position.Value.x += msc.speed * time;
    22.  
    23.             //rotate.rotation =  new Quaternio(0, rotate.rotateSpeed * time, 0, 0).normalized;
    24.             //rotate.rotation.SetEulerAngles(0f,rotate.rotateSpeed * time, 0f);
    25.             //NOTE : I THINK THIS NEEDS AN COMMAND BUFFER TO APPLY THE ROTATIONS.
    26.             //rot.Value = math.mul(rot.Value,quaternion.RotateY(math.radians(rotSpeed.rotateSpeed * time)));
    27.             float rotationThisFrame = time * rotSpeed.rotateSpeed;
    28.             var q = quaternion.AxisAngle(new float3(0.0f, 1.0f, 0.0f), rotationThisFrame);
    29.             rot.Value = math.mul(q, rot.Value);
    30.         }
    31.     }
    32.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    33.     {
    34.  
    35.         RotateJob newJob = new RotateJob{
    36.             time = Time.deltaTime
    37.    
    38.         };
    39.  
    40.         JobHandle jobHandle = newJob.Schedule(this, inputDeps);
    41.  
    42.         jobHandle.Complete();
    43.  
    44.  
    45.         return jobHandle;
    46.     }
    47. }
    Now my issue is that the move part of RotateJobSystem actually works as expected and does move the entity to the right but as you can see the Rotation part of this script I have tried several attempts at rotating.

    This is a copy/paste from the 1000 rotating cubes example on Github using a IJobForEach

    Code (CSharp):
    1. float rotationThisFrame = time * rotSpeed.rotateSpeed;
    2.             var q = quaternion.AxisAngle(new float3(0.0f, 1.0f, 0.0f), rotationThisFrame);
    3.             rot.Value = math.mul(q, rot.Value);
    Can I ask why the movement script does work but the rotation part does not??

    I cant see why a copy/pasted script (Just to see if it worked) why this does not work I updated all the references to the components.

    I can't understand why the Translation component can be updated with Translation.Value.X += but Rotation.Value cant be updated at the same time when it,s clear that this script affects all the necessary entities.

    Im thinking that maybe i have to use a buffer to update the Rotation component but could be wrong..
    Many thanks
     
    Last edited: Nov 18, 2019
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,753
    Are you sure that
    Code (CSharp):
    1. math.mul(q, rot.Value);
    not suppose to be
    Code (CSharp):
    1. math.mul(rot.Value, q);
    ?
    Is rotationThisFrame none 0?
    Try simply set any arbitrary rotation, to see, if it works that way.
    Should work in principles, as you have now.
     
  9. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    Thanks for the reply,

    I made the change that you suggested and done a Debug.Log output which results in the following output.(See Image)

    Not sure if my VS:Code setup is helping either as when I put rot.Value = math.mul() I get no intellisense to tell me what parameters the method expects.

    https://www.effectiveunity.com/ecs/04-a-first-example/

    This is the tutorial i followed to try and replicate a rotation but it doesnt seem to work either as a Component System or a Job,

    I never thought it would be so hard to do a simple Transform.Rotate(Vector3.Up(), rotateSpeed * time.DeltaTime);

    The change in action.

    Code (CSharp):
    1.    
    2.             float rotationThisFrame = time * rotSpeed.rotateSpeed;
    3.             Debug.Log("RotationThisFrame value is " +rotationThisFrame);
    4.             var q = quaternion.AxisAngle(new float3(0.0f, 1.0f, 0.0f), rotationThisFrame);
    5.             rot.Value = math.mul(rot.Value, q);
    I also tried this

    Code (csharp):
    1.  
    2. public class RotationSystem : ComponentSystem
    3.  {
    4.      private EntityQuery _enemyArray;
    5.      protected override void OnCreate()
    6.      {
    7.          _enemyArray = Entities
    8.              .WithAll<RotateSpeed, Rotation, EnemyTag>()
    9.              .ToEntityQuery();
    10.      }
    11.      protected override void OnUpdate()
    12.     {
    13.          Entities.With(_enemyArray).ForEach((ref RotateSpeed rotationSpeed, ref Rotation rotation, ref EnemyTag enemy) =>
    14.          {
    15.              rotation.Value = math.mul(rotation.Value,
    16.                  quaternion.RotateY(
    17.                      math.radians(rotationSpeed.rotateSpeed * Time.deltaTime)
    18.                  )
    19.              );
    20.          });
    21.      }
    22.  }
    23.  
    I think its best that I give up with this altogether until there is better documentation and tutorials/guides out there..

    I mean I understand how to create the entitys, and components and that the Systems/Jobs just manipulate the data that Components hold.Which is why I am not sure why I am struggling to get so much of this basic functionality to work. :(

    Also with my VS:Code if i highlight RenderMesh in the Entity Creation code it says "No definition for RenderMesh". I just loaded the same script into Visual Studio 2017 Community and done "Peek Definition" it shows me the definition and what the expected values are for a RenderMesh....

    Many thanks for all the help though!
     

    Attached Files:

    Last edited: Nov 18, 2019
  10. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    Ok after much messing around I found out a couple of things.

    1: If you use ConvertToEntity on a GameObject it creates a Rotation Component for you which can then be modified.

    2: If you create an Entity and manually Add a Rotation Component which holds a Quaternion value this seems to cause issues.

    Code (CSharp):
    1.  EntityArchetype ae = em.CreateArchetype(
    2.             typeof(Translation),
    3.             typeof(RenderMesh),
    4.             typeof(LocalToWorld),
    5.             typeof(Scale),
    6.             typeof(EnemyTag),
    7.             typeof(Rotation)
    8.    
    9.             );
    10.  
    11. em.SetComponentData(entity, new Rotation{Value = new quaternion(0,0,0,0)});
    12.  
    13.  
    this results in a NaN error on nearly all the transform components.

    now if i remove the Rotation Component it all works fine and shows the entity etc but this still leaves me unable to manipulate the variable unless I use the ConvertToEntity.

    This explains why a lot of the scripts and transform manipulation scripts you find online may not work as it appears that ConvertToEntity is doing more than just adding a component for each transform value.

    I am not expecting an answer to this, But if anyone wants to explain why I cannot manually add a Rotation Component and it only works via ConvertToEntity in the inspector and why if you try it gives you NaN error maybe it can help some one else.

    Although I am sure that there is something wrong with my addComponent and new quaternion (I,m not well versed in quaternions yet, Although I am currently reading up on them).

    Many thanks.
     

    Attached Files:

  11. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    Well this is one of your problems :) please use quaternion.identity.. I believe that is 0,0,0,1.
     
  12. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,753
    Simply
    q = quaternion.identity ;
     
  13. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Heh. I got your script from a thread this morning elsewhere on the forum and you linked this thread. I am going through the exact same learning curve and I have used Unity for 10 years in february. I don't have a comp sci degree but wrote my first goto and do math and then an X's and O's on a HP punch card machine in 1972. This whole issue of blittable types only and where to extract data to talk to my other Unity standard components is what is hanging me.

    Not that I don't get blittable types..totally get it..but how the hell do I get my paddle ring to tell the jobs system to emit a spawned entity when it has reached a particular angle. I have the Entity Struct in Scene on an object. I cannot drop the jobs or component systems anywhere on an object..so they are kinda floating in mid air when I try to figure out how to access them. I could get the paddleRing component to talk to the Jobs script..I guess..but how the blue blazes. If it ain't running a job or somewhere my mono C# script until I send it one then where is it accessed because i read that you can access the Jobs thread on the main thread. OK..tech guys..thanks for that data over and over.. Howzabout showing us instead of strutting off in pride you know some tech data about how it works., I saw those presentations too. They didn't help me yesterday at all knowing a flow chart.

    I think the script you posted on the other thread will be useful in my dissecting just which functionality talks to which functionality and when it does so and how to get the data in or out at those points. I am pretty facile and make very complex procedural applications with ease in Unity and it has put bread, butter and bacon on my table reliably. So it is not my lack of ability or insight. I know alot of tech jargon that I would not know otherwise from following probably 50k+ threads from start to finish on the forums..but honestly my eyes still gloss over on some of the tech talk behind this.. Mostly because I am impatient and just want to get back to work like I used to do with standard mono Unity C#.
     
  14. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    Ok back to update this thread with some of my findings and see if some of the pro,s can shed some light on these things.

    These 2 things are NavMesh related.

    1: Why are NavMeshAgents NOT converted to it,s Entity equivalent when using a ConvertToEntity component? (See Image)

    EnemyMovementSystem.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Entities;
    5. using UnityEngine.AI;
    6. using Unity.Transforms;
    7. using Unity.Mathematics;
    8.  
    9. public class EnemyMovementSystem : ComponentSystem
    10. {
    11.     protected override void OnUpdate()
    12.     {
    13.         var playerEntity = GetSingletonEntity<PlayerTagID>();
    14.         var playerTranslation = EntityManager.GetComponentData<Translation>(playerEntity);
    15.         Vector3 convertPos = new Vector3(playerTranslation.Value.x,playerTranslation.Value.y,playerTranslation.Value.z);
    16.         Debug.Log(convertPos);
    17.         //To Access NavMeshAgents using ConvertToEntity we must Inject the game object NavMeshAgents are NOT converted to Entity Components!!
    18.         Entities.WithAll<EnemyMovementControllerData>().ForEach((ref Translation ImagePosition, NavMeshAgent nma) =>
    19.         {
    20.                 nma.SetDestination(convertPos);
    21.         });
    22.     }
    23. }
    24.  
    25.  

    2: What is wrong with this Job?
    Code (CSharp):
    1.    
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using UnityEngine;
    6. using Unity.Transforms;
    7. using Unity.Mathematics;
    8. using UnityEngine.AI;
    9.  
    10. public class EnemyControllerMovementJobSystem : JobComponentSystem
    11. {
    12.     public struct MovementJob : IJobForEach<Translation, EnemyMovementControllerData, NavMeshAgent>
    13.     {
    14.         public float3 playerPos;
    15.         public float playerRad;
    16.         public float deltaTime;
    17.         public void Execute(ref Translation position, ref EnemyMovementControllerData msc, ref NavMeshAgent nma )
    18.         {
    19.           //We eventually pass playerposition to this.
    20.            nma.SetDestination();
    21.         }
    22.     }
    23.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    24.     {
    25.         //Set up our job..
    26.         Entity PlayerEntity = GetSingletonEntity<PlayerTagID>();
    27.         Translation PlayerPosition = EntityManager.GetComponentData<Translation>(PlayerEntity);
    28.         //float PlayerRadius = EntityManager.GetComponentData<DistanceComponent>(PlayerEntity).Radius;
    29.      
    30.         var job2 = new MovementJob
    31.         {
    32.             playerPos = PlayerPosition.Value,
    33.             deltaTime = Time.DeltaTime
    34.         };    
    35.  
    36.         JobHandle newHandle = job2.Schedule(this,inputDeps);
    37.  
    38.         newHandle.Complete();
    39.  
    40.         return newHandle;
    41.     }
    42. }
    43.  
    The script complains
    The type 'NavMeshAgent' must be a non-nullable value type in order to use it as parameter 'T2' in the generic type or method 'IJobForEach<T0, T1, T2>' [Assembly-CSharp]csharp(CS0453)

    if I change
    public void Execute(ref Translation position, ref EnemyMovementControllerData msc, ref NavMeshAgent nma )

    to
    (without the ref)
    public void Execute(ref Translation position, ref EnemyMovementControllerData msc, NavMeshAgent nma )

    I get this

    'EnemyControllerMovementJobSystem.MovementJob' does not implement interface member 'IJobForEach_CCC<Translation, EnemyMovementControllerData, NavMeshAgent>.Execute(ref Translation, ref EnemyMovementControllerData, ref NavMeshAgent)' [Assembly-CSharp]csharp(CS0535)

    If anyone can shed some light why I can use it in the ComponentSystem but not within this job it would be apreciated!
     

    Attached Files:

  15. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    This stuff baffles me too. I use something some place and can't access it in others. I was apprised of AddComponentObject for adding a Transform to an entity.. Not sure if that helps any way at all but at least the Transform now exists in ECS land. May work for other component objects that are not blittable types.
     
  16. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    851
    Generally speaking, you can only use only blittable value types in your jobs, and NavMeshAgent doesnt fall under that category(its a reference type).
    ComponentSystem is a non job, mainthread workflow of accessing data.

    This has a decent writeup on explaining the differences between reference types(ie unity's all of old gameobject components like navmeshagent, rigidbody, colliders, audiosources, transforms etc) and value types(what is the new standard way of storing data in dots)
    https://stackoverflow.com/questions...-between-a-reference-type-and-value-type-in-c

    Lastly its generally recommended now to use the new JobComponentSystem's lambda options described very thoroughly here -> https://docs.unity3d.com/Packages/com.unity.entities@0.5/manual/entities_job_foreach.html
    It can do what you were doing in ComponentSystems for the most part(ie mainthread code to access reference types), as well as using it to create easier job code.
     
  17. Shabbalaka

    Shabbalaka

    Joined:
    Jan 15, 2018
    Posts:
    154
    I think I need to look at Converting a NavMeshAgent component before I can utilise it in ECS as when I check the ConvertToEntity there is no NavMeshAgent attached, So I cannot utilise a component which does not exist.

    If you guys have any idea how this can be achieved please point me in the right direction or show me an example please.

    Many thanks!
     
  18. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    The is no NavMeshAgent equivalent on ECS at the moment, you will need to use the ConvertAndInject or create your own custom solution
     
  19. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Collections;
    5. using Unity.Entities;
    6. using Unity.Jobs;
    7. using Unity.Mathematics;
    8. using Unity.Burst;
    9. using Unity.Transforms;
    10. using Sirenix.OdinInspector;
    11.  
    12. public class ParticleEfxPool : MonoBehaviour {
    13.  
    14.     public Transform[] transformAccessArray = new Transform[400];
    15.     public GameObject[] particleSystemsAccessArray = new GameObject[400];
    16.     public bool[] isActiveArray = new bool[400];
    17.     public float3[] nextTransformPositionArray = new float3[400];
    18.     public NativeList<int> newIndexes = new NativeList<int> ();
    19.     public NativeList<float3> newPositions = new NativeList<float3> ();
    20.  
    21.     //The Job
    22.     public struct MoveParticlesJob : IJobForEach_CC<ParticleSystemFollowsMePoolData, Translation> {
    23.         public NativeArray<int> indexes;
    24.         public NativeArray<float3> positions;
    25.         ParticleEfxPool pep;
    26.         int idx;
    27.         public void Execute (ref ParticleSystemFollowsMePoolData particlesFollowMePoolData, ref Translation position) {
    28.             int poolIndex = particlesFollowMePoolData.poolIndex;
    29.             pep.newIndexes[idx] = poolIndex;
    30.             pep.newPositions[idx] = position.Value;
    31.             idx++;
    32.         }
    33.         protected override JobHandle OnUpdate (JobHandle inputDeps) {
    34.             var moveParticlesJob = new MoveParticlesJob {
    35.                 indexes = pep.newIndexes,
    36.                 positions = pep.newPositions,
    37.             };
    38.             JobHandle moveParticlesHandle = moveParticlesJob.Schedule (this, inputDeps);
    39.             moveParticlesHandle.Complete ();
    40.             return moveParticlesHandle;
    41.         }
    42.  
    43.     }
    44.     // Start is called before the first frame update
    45.  
    46.  
    47.     // Update is called once per frame
    48.     void Update () {
    49.          //hoping to use NativeLists here
    50.     }
    I am having a similar problem and cannot get the syntax correct. Every attempt..well over 100 to fashion the syntax to get a value array to use in the monobehaviour Update to set the ParticleSystem positions.
    This is how far I got in about 100 write-ups and tear back downs yesterday. Painful stuff Unity. Putting it in my ParticlePool monobehaviour allowed me some more access than when it was separate..but still no joy..
     
  20. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    851
    You can only schedule jobs on the main thread, you can't schedule jobs from jobs.
     
    ippdev likes this.
  21. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    That was my 100st moving around of code. All I want to do is get the position array and poolIndex array..Both of them are being gotten. I put them in NativeArrays. But I cannot access them in my ParticleEfxPool script. The only job I really need is getting those two arrays. I can apply the results myself in the standard Update loop. I think many folks would just like to get the data from an entity and apply said data in Update() What is the big syntax trick? Where can the results of Execute be found other than a Job?
     
  22. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    851
    Native arrays/lists/hashmaps etc are what you want for storing the results of any data manipulation(outside of using icomponentdata or buffers)
     
    ippdev likes this.
  23. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    I have tried every variation and answers like this have sent me down many dead end roads. f I create NativeArrays and stuff them with variables..yes..I have ALL the variables I need to perform the moving of ParticleSystemObjects to a new position based on their index in Update on the ParticlePoolEFX script..but I cannot access it. So the part about NativeArrays I get and they are being filled in the Job struct Execute.
    Here is the Job struct
    Code (CSharp):
    1. public class ParticleFollowsJobSystem : JobComponentSystem {
    2.     public static int length;
    3.  
    4.     //The Job
    5.     public struct MoveParticlesJob : IJobForEach_CC<ParticleSystemFollowsMePoolData, Translation> {
    6.         public NativeArray<int> indexes;
    7.         public NativeArray<float3> positions;
    8.         ParticleEfxPool pep;
    9.         int idx;
    10.         public void Execute (ref ParticleSystemFollowsMePoolData particlesFollowMePoolData, ref Translation position) {
    11.             int poolIndex = particlesFollowMePoolData.poolIndex;
    12.             indexes[idx] = poolIndex;
    13.             positions[idx] = position.Value;
    14.             pep.newIndexes[idx] = poolIndex;
    15.             pep.newPositions[idx] = position.Value;
    16.             idx++;
    17.             length = idx;
    18.         }
    19.     }
    20.     protected override JobHandle OnUpdate (JobHandle inputDeps) {
    21.         var moveParticlesJob = new MoveParticlesJob {
    22.              //what the heck goes here indexes = anything at all gives an error
    23.  
    24.         };
    25.         //returning default for now till I understand how to get this working
    26.         return default;
    27.     }
    28. }
    So the first part of the struct gives no syntax errors. When I go to OnUpdate and set up the new MoveParticlesJob I can write indexes or positions in reference to the NativeArrays in the struct, but I can't do an "=" anything in the moveParticlesJob. What the heck goes there? I am told over and over I can access these from the main thread. I have the positions, I have the indexes. I have had them since yesterday and have spent 15+ hours reading, tearing my crap up to try the "new" advice and get further from the goal. I have the two Native Arrays. I need to make sure they update in the OnUpdate job and then access the two arrays in ParticlePoolEfx or elsewhere to simply move the gameObject particle systems which are NEVER entities. Kinda like this..
    Code (CSharp):
    1. public class ParticleEfxPool : MonoBehaviour {
    2.    
    3.     public float3[] nextTransformPositionArray = new float3[400];
    4.  
    5. // Update is called once per frame
    6.     void Update () {
    7.           //if I can get this I got 20 other systems working.
    8.         nextTransformPositionArray [] = theNativeArrayFromMyJob;
    9.  
    10.  
    11. }
     
  24. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    851
    As I mentioned above you cant use a job with a reference type, in this case your monobehaviour. It is incompatible with being used in a job which require your data to be blittable value types only. So you need to decide, can you do away with that monobehaviour and find another way to structure your data that makes it job friendly? Or do you absolutely need a monobehaviour, in which case you need to structure things on the main thread(no jobs, no burst) only.

    If its the latter, then you can use the ForEach lambda, which can(among other things) do mainthread access to data. I dont really know what youre trying to do but maybe this helps if you havent used it yet -
    Code (CSharp):
    1. [AlwaysSyncronizeSystem]
    2. public class MyMainthreadSystem : JobComponentSystem
    3. {
    4.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    5.     {
    6.         var poolObject = GameObject.Find("MyPool");
    7.         var pool = poolObject.GetComponent<MyPool>();
    8.      
    9.         Entities
    10.         .ForEach((Entity entity, PoolData data, ref Translation t) =>
    11.         {
    12.             if(pool.Data.Thing == data.Thing)
    13.             {
    14.                 poolObject.transform.position = t.Value;
    15.             }
    16.         }).WithoutBurst().Run();
    17.          
    18.         return default;
    19.     }
    20. }
    the docs have far more info than I could remember, should always be your starting point
    https://docs.unity3d.com/Packages/com.unity.entities@0.5/manual/entities_job_foreach.html
     
  25. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    I have tried the ForEach in a dozen ways. I tried using the Find method in a ForEach to get a blittable array in my PoolData It always comes down to the same thing. It won't find anything monobehaviour. I am gonna give this above a shot as I see a few things left untested and it may get the GameObject and component script using that..If so the beer is on me. Just tried..the attribute[AlwaysSynchronizeSystem] is not viable. Must be more deprecated stuff. What the heck. It told me it didn't work so I started typing and autocomplete gives me the same thing and now it works..

    So far I have all the data i need to move a monobehaviour gameObject but I can't get the handle to it anywhere to use it in monobehaviour world.. I have structured data a few dozen ways and still the same block trying to get at least an array of float3's over into monobehaviour land..which acts like it is on another planet. There is no other way to structure a particle system. It lives ONLY in monobehaviour world so I have to get the position the entity it should be attached to in ECS world..which I have both a position and a pool index showing correctly for the pure ECS entities spawned...seems really simple ... but getting those two arrays into any kind of place I can use to move a non-ECS that never can be an Entity as the ParticleSystem just disappears or does not work..it will move around the transform and leave the ParticleSystem where it is, so restructuring my data type is not a useful method if I can't get the restructured data into a script where I can make use of it) it has been futile so far.
     
    Last edited: Feb 6, 2020