Search Unity

Event System

Discussion in 'Entity Component System' started by tertle, Nov 19, 2019.

  1. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    224
    Using this?
    [NativeSetThreadIndex]

    So when using an IJobEvent to read events, we add
    to the job struct, it gets auto-populated with the thread index, and thats what we pass to our concurrent ECB to make changes?
     
    Last edited: Apr 16, 2020
    lclemens and cultureulterior like this.
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Nope. That error also should not relate to events either. as it's related to using generic IComponentData/etc which the event system specifically avoids.

    That's pretty much it. I could also pass in the foreach index to use I guess to avoid this magic.
     
  3. Curlyone

    Curlyone

    Joined:
    Mar 15, 2018
    Posts:
    41
    Any documentation on how to use 'new' NativeThreadStream (where we dont need ForEach index i think) ? I am dumb so i cant understand what to do just by looking at the code, a simple example should be enough as well, when you have the time.
     
  4. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    About a week ago I grabbed and integrated the event system into my own project so I have some recent examples that work,

    To write events:
    • Add a
      NativeThreadStream.Writer
      member variable to a job
    • Inside its
      Execute()
      , call
      .Write<myEventStruct>(new myEventStruct{/*your data*/})
      on the writer

    To read events:
    • Using a job other than IJobEvent:
      • Add a
        NativeThreadStream.Reader
        member variable to a job
      • Inside its
        Execute()
        , iterate over every event like so
        Code (CSharp):
        1. for(int i=0; i<stream.ForEachCount; i++)
        2. {
        3.     var count = stream.BeginForEachIndex(i);
        4.  
        5.     for(int j=0; j<count; j++)
        6.     {
        7.         var event = stream.Read<myEventStruct>();
        8. [*]}}
    • Using IJobEvent
      • Just use the
        event
        parameter from
        Execute(myEventStruct event)
     
    Last edited: Apr 29, 2020
    NotaNaN and BackgroundMover like this.
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Egad_McDad has covered it pretty well.

    Just a note about NativeThreadStream, it has the benefits of convenience and a little better performance than NativeStream at the cost of determinism, which I think for most uses is fine.

    However, I intend to implement an option to bring back determinism at some point for specific cases that need it.

    There is also a generic version that is currently not used by the event system. I'm going to make that an option you can use as well to avoid writing bad data to events (the generic and non generic map identically to each other already.)
     
    NotaNaN and brunocoimbra like this.
  6. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    Thanks for your work @tertle !
     
    BackgroundMover likes this.
  7. Curlyone

    Curlyone

    Joined:
    Mar 15, 2018
    Posts:
    41
    Hi

    So i think i actually managed to do it and it works but i just wanted to ask if this is the correct way to do things

    This is my writer system

    Code (CSharp):
    1. public class TradeFleetCreatedEventWriterSystem : SystemBase
    2. {
    3.     EndSimulationEventSystem eventSystem;
    4.  
    5.     protected override void OnCreate()
    6.     {
    7.         eventSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EndSimulationEventSystem>();
    8.     }
    9.  
    10.     protected override void OnUpdate()
    11.     {
    12.         var writer = eventSystem.CreateEventWriter<TradeFleetCreatedEventData>();
    13.  
    14.         Entities
    15.             .WithAll<EntityCreatedTag, TradeFleetTag>()
    16.             .ForEach((Entity entity)=> {
    17.                 writer.Write(new TradeFleetCreatedEventData { });
    18.        
    19.         }).Schedule();
    20.  
    21.  
    22.         eventSystem.AddJobHandleForProducer<TradeFleetCreatedEventData>(Dependency);
    23.     }
    24. }
    This is my reader system

    Code (CSharp):
    1. public class TradeFleetCreatedEventReaderSystem : SystemBase
    2. {
    3.     EndSimulationEventSystem eventSystem;
    4.  
    5.     protected override void OnCreate()
    6.     {
    7.         eventSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EndSimulationEventSystem>();
    8.     }
    9.  
    10.     [BurstCompile]
    11.     public struct TradeFleetCreatedEventReader : IJobEvent<TradeFleetCreatedEventData>
    12.     {
    13.         public void Execute(TradeFleetCreatedEventData e)
    14.         {
    15.             //
    16.         }
    17.     }
    18.  
    19.     protected override void OnUpdate()
    20.     {
    21.         Dependency = new TradeFleetCreatedEventReader { }.ScheduleParallel<TradeFleetCreatedEventReader, TradeFleetCreatedEventData>(eventSystem, Dependency);
    22.     }
    23. }
    Is this correct way to do things ?

    Also some other question

    I want a system to run if there is/are events to read from, should i do IJobEvent as my first job and my processing Job depend on that IJobEvent, will that do it ? is there a better/proper way to do it ?

    Will there be a Run(main thread) version of IJobEvent, so that i can use it to fire events in monobehaviour scripts.

    If i wanted to add events from a monobehaviour and want to read them in ECS Systems, is that possible ? if so how can i do it ?
     
    lclemens likes this.
  8. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Yep that's pretty much it.

    There is a new system SingleEventSystemBase (and also EventSystemBase) that reads back events on main thread, but I probably should add a Run method to the job as it's definitely useful.
     
  9. Zyblade

    Zyblade

    Joined:
    Jul 1, 2014
    Posts:
    141
    So reading on main thread is possible, but reading on a monobehaviour script seems not possible, or is it?
    I got a class, which is quite complex and doesn't need to be ported to a system, performance wise. That's why I want to read event data on that monobehaviour class.
     
    TheGabelle likes this.
  10. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    hey @tertle ,

    It seems writer/reader doesn't support `BlobAssetReference<>` ? is it possible to support that ?
    I mean any reason for limiting T to unmanaged and not struct ?
     
    Last edited: May 28, 2020
  11. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
  12. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Oh sorry totally missed your message.

    It's unmanaged for an internal project reasoning, I'll look into it.
     
  13. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    great, thanks :)
     
  14. tonsillectomy

    tonsillectomy

    Joined:
    Jun 2, 2015
    Posts:
    19
    Beautiful solution. Yer a wizard @tertle !

    Quick note to anyone trying out the SampleScene for the first time. The EndSimulationEventSystem and PresentationEventSystem are deprecated and will cause an error. You can simply fix this by renaming them "EventSystemBase". Cheers!
     
    NotaNaN and Deleted User like this.
  15. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Good spot I totally forgot to update the sample.

    I've just pushed an update that fixes the sample and also changed the generic restriction to struct instead of unmanaged for @Sylmerria

    I'm working on a couple of other projects (+ job) so haven't had time to look at this too much at the moment. We use it in production so I'm pretty confident with its stability but I'm hoping to add the deterministic and generic implementations this weekend if I find some time.
     
    Last edited: Jun 16, 2020
    Egad_McDad, Sylmerria and NotaNaN like this.
  16. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    oh great thanks :)
     
  17. karadumankcan

    karadumankcan

    Joined:
    Jun 8, 2020
    Posts:
    7
    Hello^^

    Is there way to be able to run a system when there is a certain event exist ? (idc about data, just existance)
    I am making a "tick" system and i want some systems to run only when tick is.. ticked, i am using a system like this:

    Code (CSharp):
    1.  
    2.         var deltaTime = Time.DeltaTime;
    3.         var tickEvent = eventSystem.CreateEventWriter<TickElapsed>();
    4.  
    5.         Entities.ForEach((ref TickTimerData timerData) => {
    6.             timerData.currentTime += deltaTime;
    7.  
    8.             if (timerData.currentTime > timerData.maxTime)
    9.             {
    10.                 timerData.currentTime -= timerData.maxTime;
    11.                 tickEvent.Write(new TickElapsed { });
    12.             }
    13.         }).Schedule();
    14.  
    15.         eventSystem.AddJobHandleForProducer<TickElapsed>(Dependency);
    16.  
    i wanted to use eventSystem.GetEventReadersCount<TickElapsed>() and if this returns 1 then it would mean Tick has elapsed, if 0 that means it didnt, but for some reason it always returns 1(i am using Debug.Log on OnUpdate method of a system, it returns 0 for 2 times and it returns 1 after that), as a work around i am using IJobEvent<TickElapsed> and send native array of bool there, and set it to true if it runs, then i do Complete on the job and check the value, if value is true then i run the 'real' job, but this will make lots of boilerplate, is there a way to do this properly ? or workaround is the way to go ?

    Thanks for your work also^^
     
  18. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    GetEventReadersCount is effectively just the number of times you've called CreateEventWriter since the last update.
    It's very useful if you combo it with ChangeFilter to stop creating event queues to early out (though you can use the shortcut HasEventReaders).

    It's not the number of values that are stored in the writers (there's no way to know without querying the result)

    I do somewhat have a solution to this already though. It's in the EventSystemBase.Extensions that calculates the number of events to ensure a hashmap has capacity. I could expose the count part.
     
  19. tonsillectomy

    tonsillectomy

    Joined:
    Jun 2, 2015
    Posts:
    19
    Okay, either I'm dumb, or we have a prime example of curse of knowledge ("A cognitive bias that occurs when an individual, communicating with other individuals, unknowingly assumes that the others have the background to understand"), or both.

    So I have been trying to get this to work for a while now, but no dice. The problem is that there are heaps of code examples which are deprecated or just insufficient, so I can't really use them as learning material, and thus my attemps to combine these examples always gives birth to C# equivalent of Frankenstein's monster.

    So is it possible to get an updated example of the correct usage of this beautiful system? Here's an example, which should be simple and relatable for everyone:

    Let's say we have a system: "HealthUpdateEventWriter". This system collects an array of floats, representing the change of HP of each entity in an EntityQuery. These entities have a component called "HealthComponent" and just for the sake of the example; we want to update these values in a different system, called "HealthUpdateEventReader".

    In "HealthUpdateEventReader" we'll combine the HP changes of each entity and pass them to a separate array, which again is used for updating the "HealthComponent" values (how the values are updated is irrelevant, I just want to get a clear example on how to pass arrays of data, assigned for a specific component of a specific entity).

    Now this old example could be repurposed into "HealthUpdateEventWriter", but it doesn't seem to work anymore:
    Code (CSharp):
    1. [BurstCompile]
    2. private struct ProduceJob : IJobParallelFor
    3. {
    4.     public NativeStream.Writer Events;
    5.     public Random Random;
    6.     public void Execute(int index)
    7.     {
    8.         this.Random.state = (uint)(this.Random.state + index);
    9.         var eventCount = this.Random.NextInt(1, 1000);
    10.         this.Events.BeginForEachIndex(index);
    11.    
    12.         this.Events.Write(default(TestEventEmpty));
    13.    
    14.         for (var i = 0; i < eventCount; i++)
    15.         {
    16.             this.Events.Write(i);
    17.         }
    18.         this.Events.EndForEachIndex();
    19.     }
    20. }

    How could I make that sort of thingy with the current approach?

    Also, it would be nice to have examples both in IJobParallelFor and IJobEvent formats. It's quite confusing trying to figure this thing out without a clear, simple example, which would include all the steps required and nothing more. Then again, the possibility of me just being dumb is still on the table. In that case, I demand an example for us simpletons!

    Thanks! :)
     
  20. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Yeah sorry this thread is a bit out dated but there is a sample that is included in the package you can use as reference.
    In the package manager, find the eventsystem package and click import samples.

    I'll add updating documentation to the ever growing list of things I need to do.
     
    Last edited: Jun 27, 2020
    charbean and Sylmerria like this.
  21. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Started work on 1.1, my current proposal is going to have a couple of changes with the goal of adding the option of determinism and generics.

    Bag - nondeterminstic, convenient and fast to use in Entities.ForEach (generic version of the current implementation)

    Code (CSharp):
    1.             EventWriter.Bag<MyEvent> bag = this.eventSystem.CreateEventWriter<MyEvent>();
    2.  
    3.             this.Entities.ForEach((Entity entity, int entityInQueryIndex) =>
    4.                 {
    5.                     bag.Write(default(MyEvent));
    6.                 })
    7.                 .ScheduleParallel();
    Stream - deterministic but a bit more effort and a little slower in Entities.ForEach

    Code (CSharp):
    1. EventWriter.Stream<MyEvent> stream = this.eventSystem.CreateEventWriter<MyEvent>(this.eventQuery.CalculateEntityCount());
    2.  
    3. this.Entities.ForEach((Entity entity, int entityInQueryIndex) =>
    4.     {
    5.         stream.BeginForEachIndex(entityInQueryIndex);
    6.         stream.Write(default(MyEvent));
    7.     })
    8.     .WithStoreEntityQueryInField(ref this.eventQuery)
    9.     .ScheduleParallel();
    For safety these are both now generic by default, however a non generic version to pass a variety of data will be provided just struggling to think of good naming to convert

    They all map to the same memory so use the exact same reader.
     
  22. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    Unity 2020.1.0b14, Burst 1.3.3, Entities 0.11.1-preview.4.

    When I run Samples/BovineLabs Event/1.0.1/Scenes/SampleScene, there are hundreds of messages in the console saying:

    Internal: JobTempAlloc has allocations that are more than 4 frames old - this is not allowed and likely a leak

    and thousands saying....

    Internal: deleting an allocation that is older than its permitted lifetime of 4 frames (age = 15)
    Unity.Collections.LowLevel.Unsafe.UnsafeUtility:Free(Void*, Allocator)
    BovineLabs.Event.Containers.UnsafeThreadStream:Deallocate() (at Library/PackageCache/com.bovinelabs.event@2aa3de8cc1/BovineLabs.Event/Containers/UnsafeThreadStream.cs:157)
    BovineLabs.Event.Containers.DisposeJob:Execute() (at Library/PackageCache/com.bovinelabs.event@2aa3de8cc1/BovineLabs.Event/Containers/UnsafeThreadStream.cs:380)
    Unity.Jobs.JobStruct`1:Execute(DisposeJob&, IntPtr, IntPtr, JobRanges&, Int32)


    Is that normal?
     
    Last edited: Jul 3, 2020
  23. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    It's just because the fixed update runs at 50fps and your pc is too powerful and your fps is likely above 200. If you go into the sample code and increase the events per second to drop your fps it'll go away.
     
  24. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    I think I figured it out...

    On the Hierarchy left I needed to select Event system:
    upload_2020-7-3_16-28-2.png
    And then in the inspector I changed "First Selected" to UpdateEvents:
    upload_2020-7-3_16-29-1.png

    Now when I run there are no warnings and the HUD looks like this:

    upload_2020-7-3_16-27-33.png
     
  25. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Interesting. That event system has nothing to do with the this (that's Unity UI), but whatever works (it just shares an unfortunate name.)
     
  26. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    Lol! I thought so too, but I was out of ideas. In in that case... I have no idea why the warnings went away.
     
  27. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    A word of caution - just adding the examples to a project (Samples/BovineLabs) will cause all scenes to take a massive performance hit because some of the systems in the sample will run even if you don't have the sample scene open.

    I was pretty confused as to why my game was getting 10fps until I did a deep profile.

    upload_2020-7-3_17-29-58.png

    I guess that's a side-effect of Unity running any and every system it finds :)
     
  28. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Yes. The sample is not well built! When I finished some revisions I'm going to update the sample and make it a lot more versatile (on the fly tweaking of event count, core usage, type of event, senders etc) but I'll also make it generate entities from the scene so it won't affect other parts of project.

    At the moment it's really just more of a stress test.
     
  29. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    I'm really looking forward to that "bag" style example above. It looks so clean and easy to use!
     
  30. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Good news then, that is already how it is implemented!
    This code is completely valid with the current version.

    Code (CSharp):
    1.             var writer = this.eventSystem.CreateEventWriter<TestEventEmpty>();
    2.          
    3.             this.Entities.ForEach((Entity entity) =>
    4.             {
    5.                 writer.Write(new TestEventEmpty());
    6.             }).ScheduleParallel();
    7.          
    8.             this.eventSystem.AddJobHandleForProducer<TestEventEmpty>(this.Dependency);
    What I'm adding back is the option for determinism for anyone who needs it.
     
    lclemens likes this.
  31. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    OK. I've setup the deterministic mode and updated the samples, took a bit longer than I expected as I also found a couple of bugs I didn't expect to find during the process (related to multiple worlds).

    If you want early access to the 1.1 version, you can pull the dev branch
    https://gitlab.com/tertle/com.bovinelabs.event/-/tree/dev

    I intend to improve the documentation and enable the generics mode before merging it to master.

    For the samples, I added the option to let you change number of threads and events so you can test scale. Note you will hit the Unity fallback memory allocator long before this starts to struggle (and then this system will run a lot slower.)

    public NativeEventStream.Writer CreateEventWriter<T>()
    public NativeEventStream.Writer CreateEventWriter<T>(int foreachCount)

    If you want to use the existing, non-deterministic but simpler implementation just do what you were already doing.
    If you need determinism, pass in your foreachCount and make sure you call BeginForEach(int) for each count.

    There is a safety check in here that will throw an exception if you call BeginForEach in thread mode, or don't call BeginForEach when you've set a foreachCount.

    One final thing, there is a new EventSystemBase.UsePersistentAllocator option (off by default) that can be used to avoid allocator warnings when using the system across 2 worlds with different update rates. Slightly slower as expected, but not hugely.
     
  32. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    1.1
    Added

    • Added deterministic mode. Use CreateEventWriter<T>(forEachCount). Must prefix writes with stream.BeginForEachIndex(index) just like NativeStream (there is no EndForEachIndex though)
    • Added a persistent allocator option which is useful for when you are using worlds with different update rates to avoid leaks.
    Updated
    • Updated stress test sample. New options to tweak the stress test. Will now only run if you load the scene.
    upload_2020-7-8_9-43-8.png

    Fixed
    • Fixed multi world eventsystems actually releasing deferred streams properly now
    • Fixed disabled domain reloading issue with multi event systems.
    Changes
    • Writer now needs to be passed by ref to other methods. There is a safety check on here in case you forget.

    Doesn't include generics yet (it's built I just haven't found a way I like integrating it)

    I intend to update the original thread in this post soon as most of it is legacy, and write some modern documentation onto the git page.
     
    Last edited: Jul 8, 2020
    Egad_McDad, Scorr, Sylmerria and 7 others like this.
  33. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    761
    Man you were busy over the weekend! Thank you!!
     
  34. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Last edited: Jul 9, 2020
  35. nopacc

    nopacc

    Joined:
    Jul 13, 2017
    Posts:
    5
    Nice work for your documentation!
     
  36. matpaul

    matpaul

    Joined:
    Jul 24, 2019
    Posts:
    5
    @tertle Hi!
    On 1.1.3 I have fatal Thread 1: EXC_BAD_ACCESS only in release mode on iOS - in editor & development mode with script debug everything is ok

    Run sample project - it's ok - no fatal

    My code is UI button with onClickHandler
    Code (CSharp):
    1.  
    2. var healthUpdateEvent = new HealthUpdateEvent()
    3. {
    4.     fromValue = fromValue,
    5.     toValue = toValue,
    6.     owner = ownerEntity,
    7. };
    8. fromValue = toValue;
    9.  
    10. eventWriter.Write(healthUpdateEvent);
    11. eventSystem.AddJobHandleForProducer<HealthUpdateEvent>(default);
    12.  
     
  37. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    So the sample project is running fine on iOS release builds?

    Annoyingly I don't have an iOS device to test, but it has been tested on other AOT platforms (il2cpp windows, xbox, ps4) in release mode.

    Can you 100% confirm it is actually crashing in the event system? (iterate the events but comment out any action that the HealthUpdateEvent)
     
  38. matpaul

    matpaul

    Joined:
    Jul 24, 2019
    Posts:
    5
    Sample project is fine on iOS
    Check on android - it's ok

    Confirm, remove all my external systems not help

    source:
    Code (CSharp):
    1.  
    2. public class HealthBarDebug : MonoBehaviour, IConvertGameObjectToEntity
    3. {
    4.     public GameObject owner;
    5.     public Entity ownerEntity;
    6.  
    7.     private float fromValue = 1;
    8.     private float toValue = 1;
    9.  
    10.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    11.     {
    12.         ownerEntity = conversionSystem.GetPrimaryEntity(owner);
    13.         Debug.Log(ownerEntity);
    14.     }
    15.  
    16.     public void HandleHitClick()
    17.     {
    18.         var eventSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EventSystem>();
    19.         var eventWriter = eventSystem.CreateEventWriter<HealthUpdateEvent>();
    20.        
    21.         toValue -= 0.2f;
    22.        
    23.         var healthUpdateEvent = new HealthUpdateEvent()
    24.         {
    25.             fromValue = fromValue,
    26.             toValue = toValue,
    27.             owner = ownerEntity,
    28.         };
    29.         fromValue = toValue;
    30.        
    31.         eventWriter.Write(healthUpdateEvent); // <-- FATAL HERE
    32.         eventSystem.AddJobHandleForProducer<HealthUpdateEvent>(default);
    33.         Debug.Log("BUTTON CLICK -> send event");
    34.     }
    35. }
     
  39. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Hmm now that I think of it, this might be similar to an il2cpp ps4 issue we noticed a while ago. I suspect it you were using native stream here instead you'd have the same issue.

    About to head to bed but I'll dig up my old notes about the issue including a workaround tomorrow
     
    matpaul likes this.
  40. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    ok, to follow up on this the issue someone noticed at one point when building for PS4 was that for some reason it doesn't like this code in a NativeStream when built with IL2CPP and run on main thread.

    Code (CSharp):
    1. public void Write<T>(T value) where T : struct
    2. {
    3.     ref T dst = ref Allocate<T>();
    4.     dst = value;
    5. }
    The EventStream uses the exact same code so maybe there is a similar issue on iOS. Can you try run this code instead? Basically just put the call inside a burst compiled job.

    Code (CSharp):
    1. public void HandleHitClick()
    2. {
    3.    var eventSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EventSystem>();
    4.    var eventWriter = eventSystem.CreateEventWriter<HealthUpdateEvent>();
    5.  
    6.    toValue -= 0.2f;
    7.  
    8.    var healthUpdateEvent = new HealthUpdateEvent()
    9.    {
    10.        fromValue = fromValue,
    11.        toValue = toValue,
    12.        owner = ownerEntity,
    13.    };
    14.    fromValue = toValue;
    15.  
    16.    var handle = new EventJob
    17.    {
    18.        HealthEvent = healthUpdateEvent,
    19.        EventStream = eventWriter
    20.    }
    21.    .Schedule();
    22.  
    23.    eventSystem.AddJobHandleForProducer<HealthUpdateEvent>(handle);
    24.  
    25.    handle.Complete(); // optional
    26.  
    27.    Debug.Log("BUTTON CLICK -> send event");
    28. }
    29.  
    30.  
    31. [BurstCompile]
    32. private struct EventJob : IJob
    33. {
    34.    public HealthUpdateEvent HealthEvent;
    35.    public NativeEventStream.Writer EventStream;
    36.  
    37.    public void Execute()
    38.    {
    39.        EventStream.Write(HealthEvent);
    40.    }
    41. }
    (I wrote it in notepad so might have a silly syntax error)
     
    brunocoimbra and matpaul like this.
  41. matpaul

    matpaul

    Joined:
    Jul 24, 2019
    Posts:
    5
    It's help, thank you!
     
  42. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    yeah so this is a Unity issue. I really need to get around to reporting it. Annoyingly both the platforms (PS4 and now iOS) that seem to have the issue are the 2 platforms I don't have access to at the moment in lock down.
     
  43. karadumankcan

    karadumankcan

    Joined:
    Jun 8, 2020
    Posts:
    7
    Hello

    Is there a proper way to get events a native list or array ?

    my use case is, i want to get events as native list or array and read those inside ForEach lambda and do some processing (for example, i have threat tables on my entities, and i want to remove threat table entry if an entitiy inside that table is destroyed), right now i am doing IJobEvent<> as my first job and populate a native list and use that native list inside ForEach lambda, any suggestions ?

    Another question, what kind of plans you have for this event system, any plans for future ?

    PS: Thanks for the GetEventCount method^^
     
  44. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    [1.1.4] - 2020-08-06
    Added
    • Added Schedule for IJobEvent for when you don't want parallel scheduling
    • Added new extension, ToNativeList
    As for future plans, none really - I'm very happy with the project is at the moment and there's nothing in particular I feel it's missing (except some generic safety.) I'll add features and extensions as I come along problems or someone has a request I think is sensible.

    (There's no magic for ToNativeList. It's unlikely much faster than if you just created your own job and added to it, just a convenience)
     
    Last edited: Aug 6, 2020
    florianhanke and brunocoimbra like this.
  45. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    @tertle just want to express my gratitude for this package, have been using it for a while and... well, only good things to say about it!
     
    Egad_McDad, NotaNaN and tertle like this.
  46. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    @tertle , I'm not using your package but it help me understant lots of things regarding native streams so if I may provide an idea for a new feature : delayed events.

    In some case, maybe I want to trigger an event in a frame but make it "consumable" in X seconds.
     
  47. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    i can see why this would be a (maybe even common) suggestion, but I don't think it really fits the library and has some technical issues.

    For starters, would have to switch from tempjob memory to persistent. The package already actually supports changing this in the case where you are using it across worlds with vastly different update rates, but it runs about 10% slower.

    Also I think that'd be a very specific use case that is better handling by the application.

    Mainly I don't think it fits my vision of the library. I know a lot of people use it for gameplay which is completely fine and there is a time/place; personally though I mostly use it for tools. Things such as collecting analytics, a burstable gizmo drawing library, sending networked messages etc
     
  48. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    369
    @tertle after updating to lastest version (1.1.4), I have compilations errors like ( I already tried to clean my package cache) :

    Code (CSharp):
    1. Library\PackageCache\com.bovinelabs.event@aa50263740\BovineLabs.Event\Jobs\IJobEventReaderForEach.cs(62,34): error CS0117: 'ScheduleMode' does not contain a definition for 'Parallel'
    Code (CSharp):
    1. Library\PackageCache\com.bovinelabs.event@aa50263740\BovineLabs.Event\Jobs\IJobEventReaderForEach.cs(110,25): error CS1503: Argument 2: cannot convert from 'System.Type' to 'Unity.Jobs.LowLevel.Unsafe.JobType'
    2.  
     
    Last edited: Aug 9, 2020
  49. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    What version of Unity/entities?

    -edit-

    ok I can repo it in 19.4

    Seems the the ScheduleMode was changed in 2020.1 or 2020.2 (was using .2)
    Let me figure out when this was and conditional it.

    -edit2-

    yeah in 2020.2. few other tweaks to job scheduling that I missed as well. Let me fix this up quickly
     
    Last edited: Aug 9, 2020
    Sylmerria likes this.
  50. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Ok should be fixed. I suspect unity just auto updated api when I loaded it in 2020.2 and I missed it.

    I haven't thoroughly tested this yet except to ensure all my tests are passing.