Search Unity

Get Blob data with Singleton?

Discussion in 'Entity Component System' started by calabi, Oct 14, 2019.

  1. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    Is this possible or the correct way? I need some Blob data in a job with some other data. I'm basically using the below code but I'm pretty sure its not working correctly. Do I need to get it by ref somehow?
    Code (CSharp):
    1.  var dudewtf = GetSingleton<WaypointWalker>();
    2.  
    3.      
    4.         var jobtuner = new TurnTowardsjob()
    5.         {
    6.      
    7.             blobbypoints = dudewtf.Waypoints.Value.Waypoints
    8.  
    9.         };
    edit: So it seems like getting the Blobdata with Getsingleton works but setting it in that manner somehow makes all the values incorrect. I'm presuming because its not by ref?
     
    Last edited: Oct 14, 2019
  2. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    Yes, you need to get everything in the blob (including the blob itself) by ref.

    They'll be adding a compiler check at some point to make non-ref access an error.

    I'm about to publish an updated custom package that has a lot helpers for this type of use case (along with unit tested examples). Stay tuned. I'll put an update to this thread when I do.

    Should go up tonight or tomorrow evening PST.
     
  3. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    Thanks I'm curious how would I get the blob by ref then, because neither of the below code works.

    Code (CSharp):
    1. ref var dudewtf = ref GetSingleton<WaypointWalker>();
    2.  
    3.  
    4. ref var tempblob = ref Blobbypoints;
    Edit: Nevermind the second statement seems to be working now for some reason, but still the values arent the correct values, maybe I have a bug somewhere else though.
     
    Last edited: Oct 15, 2019
  4. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    So I still cannot get the Blob data's to work inside a job I've tried every combination and method I can think and cannot find the right code. I can get the blob data fine outside the job I can check the values and they all come back correct. But inside the job the data just becomes garbage, incorrect data no matter what I do it seems. Here's the code I currently have if anyone can figure out what I'm doing wrong.

    Code (CSharp):
    1. public class TurnTowardsWhatever : JobComponentSystem
    2. {
    3.  
    4.     public EntityQuery ma_query;
    5.     protected override void OnCreate()
    6.     {  
    7.         RequireSingletonForUpdate<PauseSystemsCompTag>();
    8.         ma_query = GetEntityQuery(typeof(WaypointWalker));
    9.  
    10.     }
    11.     //[BurstCompile]
    12.     struct TurnTowardsjob : IJobForEach<Translation, Rotation, ToCurrentWaypoint>
    13.     {    
    14.         [DeallocateOnJobCompletion]
    15.         public BlobArray<float3>  blobbypoints;
    16.    
    17.         public void Execute(ref Translation transit, ref Rotation rutate, ref ToCurrentWaypoint dudud)
    18.         {
    19.             ref var tempblob = ref blobbypoints;
    20.        
    21.             float3 heading = tempblob[dudud.value] - transit.Value;
    22.             for (int i = 0; i < tempblob.Length; i++)
    23.             {
    24.                 Debug.Log("Current Waypoint inside job is equal to " + tempblob[i]);
    25.             }    
    26.             heading.y = 0f;
    27.             rutate.Value = quaternion.LookRotation(heading, math.up());
    28.  
    29.         }
    30.     }
    31.  
    32.  
    33.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    34.     {        
    35.         //var dudewalker = GetSingleton<WaypointWalker>();
    36.  
    37.         //ref var tempblob = ref dudewalker.Waypoints.Value.Waypoints;    
    38.  
    39.         var dudewmaypoint = ma_query.GetSingleton<WaypointWalker>();  
    40.  
    41.         ref var duddly = ref dudewmaypoint;
    42.    
    43. //        for (int i = 0; i < duddly.Waypoints.Value.Waypoints.Length; i++)
    44. //        {
    45. //            Debug.Log("Current Waypoint outside job is equal" + duddly.Waypoints.Value.Waypoints[i]);
    46. //        }
    47.  
    48.         var jobtuner = new TurnTowardsjob()
    49.         {
    50.      
    51.             blobbypoints = duddly.Waypoints.Value.Waypoints
    52.        
    53.  
    54.         };
    55.    
    56.         return jobtuner.ScheduleSingle(this, inputDeps);
    57.  
    58.     }
    59. }
     
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    Always pass the BlobAssetReference or the struct containing the BlobAssetReference into the job and access what you need from the job.

    And in case you are wondering why (warning: technical): Blobs rely on relative addressing hardware to gain speed-ups when reading the data while allowing the structure to be dynamically-sized with respect to type. In consequence, the blob can't be split up as it will break the relative addressing. For passing stuff into a job you have to give the job the root address. And for passing stuff around while inside of a job you have to use ref so that the offset addresses are captured relative to the root.
     
    calabi, psuong and sschoener like this.
  6. sschoener

    sschoener

    Joined:
    Aug 18, 2014
    Posts:
    73
    Here is a usage example:
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5.  
    6. public struct TestBlob
    7. {
    8.     public int Value;
    9. }
    10.  
    11. public struct TestComponent : IComponentData
    12. {
    13.     public BlobAssetReference<TestBlob> Blob;
    14. }
    15.  
    16. [AlwaysUpdateSystem]
    17. public class TestSystem : JobComponentSystem
    18. {
    19.     private BlobAssetReference<TestBlob> CreateBlob()
    20.     {
    21.         using (var builder = new BlobBuilder(Allocator.Temp))
    22.         {
    23.             ref var data = ref builder.ConstructRoot<TestBlob>();
    24.             data.Value = 42;
    25.             return builder.CreateBlobAssetReference<TestBlob>(Allocator.Persistent);
    26.         }
    27.     }
    28.  
    29.     protected override void OnCreate()
    30.     {
    31.         var entity = EntityManager.CreateEntity(typeof(TestComponent));
    32.         EntityManager.SetComponentData(entity, new TestComponent{
    33.             Blob = CreateBlob()
    34.         });
    35.     }
    36.  
    37.     [BurstCompile]
    38.     private struct TestJob : IJob
    39.     {
    40.         public BlobAssetReference<TestBlob> BlobData;
    41.         public NativeArray<int> OutputValue;
    42.         public void Execute()
    43.         {
    44.             OutputValue[0] = BlobData.Value.Value;
    45.         }
    46.     }
    47.  
    48.     protected override JobHandle OnUpdate(JobHandle inputDependencies)
    49.     {
    50.         var job = new TestJob() {
    51.             BlobData = GetSingleton<TestComponent>().Blob,
    52.             OutputValue = new NativeArray<int>(1, Allocator.TempJob),
    53.         };
    54.         job.Schedule(inputDependencies).Complete();
    55.         UnityEngine.Debug.Assert(job.OutputValue[0] == 42);
    56.         job.OutputValue.Dispose();
    57.         return default;
    58.     }
    59. }
     
    echeg and calabi like this.
  7. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    Awesome, thanks guys, that was really helpful, I worked it out.

    I just got it by declaring inside the job then.

    public WaypointWalker waypointdudes;

    then assigning it by

    waypointdudes = GetSingleton<WaypointWalker>();

    then using the below in the execute.

    ref var tempblob = ref waypointdudes.Waypoints.Value.Waypoints;
     
  8. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    calabi likes this.