Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Event System

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

  1. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    I am using events 2.1.0. This morning I updated from DOTS 1.0.0-pre.15 to 1.0.0-pre.44. After doing that, there was an error about some dll. So I decided to restart unity, and then unity crashed (which it seems to do pretty a lot these days). When it came back up, I started getting the error:

    "Library\PackageCache\com.bovinelabs.event@753d75da33\BovineLabs.Event\Systems\EventConsumer.cs(86,80): error CS0246: The type or namespace name 'NativeMultiHashMap<,>' could not be found (are you missing a using directive or an assembly reference?)"

    I looked at the release notes and didn't see anything about NativeMultiHashMap being removed in the pre.44 release, but I think it might have been replaced by NativeParallelMultiHashMap ? It uses unity.collections 2.1.0-pre.11.
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    yeah it's been renamed.

    i'll make an update at some point to change it over but it's about 5th on my priorities atm since I don't actually use this library anymore in my project.

    if you need it quick just make a local copy and find replace NativeMultiHashMap -> NativeParallelMultiHashMap
     
    Last edited: Feb 18, 2023
    Sylmerria and lclemens like this.
  3. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    That's exactly what I did. But I'm curious why you're not using the event library anymore. Did you find a better solution, or is it just because you don't need events anymore, or is there some other reason?
     
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    I haven't used it in like a year. Before that I only really ever used it for debugging tools and I moved those over to a case-by-case singleton implementation but utilizing the NativeEventStream from this library.

    My libraries are heavily reliant on ChangeFilters and they provide enough of an event like experience.
     
    UniqueCode likes this.
  5. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    In the latest versions of DOTS 1.0, how would I go about writing to an event from a monobehaviour?

    I used to do this:

    Code (CSharp):
    1. EventSystem es = Unity.Entities.World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<EventSystem>();
    2. BovineLabs.Event.Containers.NativeEventStream.ThreadWriter writer = es.CreateEventWriter<MyEvent>();
    3. writer.Write(new MyEvent{ val = 1.5f });
    4. es.AddJobHandleForProducer<MyEvent>(default);
    5.  
    But now it's not possible to fetch a system like that...


    Cannot implicitly convert type 'Unity.Entities.SystemHandle' to 'BovineLabs.Event.Systems.EventSystem'
    The type name 'ThreadWriter' does not exist in the type 'NativeEventStream'
    'EventSystem' does not contain a definition for 'CreateEventWriter' and no accessible extension method 'CreateEventWriter' accepting a first argument of type 'EventSystem' could be found (are you missing a using directive or an assembly reference?)
    'EventSystem' does not contain a definition for 'AddJobHandleForProducer' and no accessible extension method 'AddJobHandleForProducer' accepting a first argument of type 'EventSystem' could be found (are you missing a using directive or an assembly reference?)
     
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    You've reminded me I never updated this.

    So it's not designed for this really. I'm strongly against ever having your mono world pass or read data from the entity world (I think systems should be responsible for passing required data to monobehaviours but not the other way.)

    That said, I think it's still doable.
    To start with you'd need to use GetSystemManaged to get the actual system.
    Call RegisterProducer to get your producer.
    Then use that to create your event stream.


    Anyway if anyone is interested in what I use these days, wrote up an alternative to this event system which is basically a nice easy way to replicate the EntityCommandBuffer singleton pattern
    https://gitlab.com/tertle/com.bovinelabs.core/-/tree/master/BovineLabs.Core/SingletonCollection
     
    Last edited: Mar 8, 2023
  7. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    Thanks!! The main reason I'm passing data to the entity world from the mono world is because I have a GUI with a bunch of button handlers in it using the new input system and I haven't gone through the pain of converting all GUI inputs, button handling, touchscreen input, drag-and-drop/google-earth-style-drag, camera control, etc into the entity domain. So for now, I occasionally break the rule. Since it's all one-time things like button presses that need to run in the main thread anyway (Unity is still stuck in the mono world for input and GUI), it doesn't hurt performance.

    I guess I'm not really sure how one would go about using that SingletonCollection in place of events (CreateWriter maybe?), but I suspect some guys out there smarter than me might be able to use it.
     
  8. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    It's reasonably easy. Sharing containers between systems is popular so I just made a very easy and generic way to handle it. If you did it with NativeEventStream then it's pretty much the same as this event system except going through some event system.

    Reader / setup

    Code (CSharp):
    1.     public unsafe partial struct TestSystem : ISystem
    2.     {
    3.         private SingletonCollectionUtil<Singleton, NativeList<int>> singletonUtil;
    4.         public void OnCreate(ref SystemState state) => this.singletonUtil = new SingletonCollectionUtil<Singleton, NativeList<int>>(ref state);
    5.         public void OnDestroy(ref SystemState state) => this.singletonUtil.Dispose();
    6.  
    7.         [BurstCompile]
    8.         public void OnUpdate(ref SystemState state)
    9.         {
    10.             // If you want to use on main thread like EntityCommandBufferSystem call state.Dependency.Complete();
    11.             UnsafeList<NativeList<int>>.ReadOnly streams = this.singletonUtil.Streams;
    12.             for (var i = 0; i < streams.Length; i++)
    13.             {
    14.                 state.Dependency = new TestReadJob { Results = streams.Ptr[i] }.Schedule(state.Dependency);
    15.             }
    16.  
    17.             this.singletonUtil.ClearRewind();
    18.         }
    19.  
    20.         public struct Singleton : ISingletonCollection<NativeList<int>>
    21.         {
    22.             // Recommended to use explicit implementation to hide from users
    23.             UnsafeList<NativeList<int>>* ISingletonCollection<NativeList<int>>.Collections { get; set; }
    24.             Allocator ISingletonCollection<NativeList<int>>.Allocator { get; set; }
    25.         }
    Writing

    Code (CSharp):
    1.     public partial struct TestWriteSystem : ISystem
    2.     {
    3.         [BurstCompile]
    4.         public void OnUpdate(ref SystemState state)
    5.         {
    6.             NativeList<int> list = SystemAPI.GetSingleton<TestSystem.Singleton>().CreateList<TestSystem.Singleton, int>(16);
    7.             state.Dependency = new TestWriteJob { List = list }.Schedule(state.Dependency);
    8.         }
    currently supports, NativeArray, NativeList, NativeQueue, NativeHashMap, NativeParallelHashMap, NativeParallelMultiHashMap and my custom NativeEventStream (what this eventsystem was using)

    Adding support for a new container is just a 4 line extension method

    Under the hood it uses its own dual rewind allocators to allow non blocking event chaining

    Only annoyance I have is having to explicitly define the generics .CreateList<TestSystem.Singleton, int> because of c# limitations
     
    Last edited: Mar 9, 2023
    Carrotpie and TheSmokingGnu like this.
  9. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    1,068
    Hey @tertle,

    I recall that you previously mentioned not using this package for game simulation and instead only utilizing it for statistical purposes.
    I am currently planning to develop a package that heavily relies on events and I aim to avoid delaying events to the next frame or creating synch points.

    Can you please provide more details about your decision?

    Thank you.
     
  10. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    All I can really say is it just doesn't feel right for ECS and I haven't felt the need for an event framework in ~2years.

    I haven't used this library in 1.0 at all and replaced all my tools usages with a singleton container for sharing a collection of containers (similar to ECBS singleton but more generic and with double allocators to allow sync point less sharing and also supporting most containers)
    https://gitlab.com/tertle/com.bovinelabs.core/-/tree/master/BovineLabs.Core/SingletonCollection
     
    Laicasaane and Opeth001 like this.
  11. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    365
    Hi !

    Do you still plan to update this package to 1.0 ?
     
  12. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    Is it broken? It's been mostly maintained in 1.0 and if it's broken I'll patch it as it should be easy for anyone who is already using it.
    I generally recommend alternatives found in my core library now though.
     
  13. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    365
    Oh it's already upgraded ? nice, reading previous post seems to me it was not the case.

    > I generally recommend alternatives found in my core library now though.
    This system is better than using entities as notification.
    But I'm curious about why the "SingletonCollectionUtil" is better than your EventSystem from your pdv because like you said it's almost the same if you pass by a nativeStream.
     
  14. lclemens

    lclemens

    Joined:
    Feb 15, 2020
    Posts:
    714
    Just thinking out loud here and it's possible I'm misunderstanding the code, but these are my two main concerns with the SingletonCollectionUtil approach:
    1. That reader code is a ton of boilerplate just to read an event... Ideally I would just write a simple foreach and perhaps loop through a list of events in a stream.

    2. It looks to me like it is not one-to-many.... in other words I can't just write an event and then all reader systems and jobs will read it (I think that ClearRewind() is removing the events so other threads won't read them). Also, it looks like it would break if the reader reads before the writer writes unless I organize the systems/jobs to be in the correct order. What if I have some systems/jobs that both read and write events? It could end up in a situation where it is impossible to both read and write the events needed due to a chicken-or-the-egg paradox.
    I think an ideal setup would be something that has minimal boilerplate and any job can push an "event" at any time during a frame and N number of readers will be guaranteed to read them once regardless of order. A single cleanup system would be nice too so the developer wouldn't need to worry about which job does the cleanup. I suspect the downside to all that flexibility would be that readers would get the frames one frame late, but to me that seems like an acceptable compromise for most situations.
     
  15. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    365
    hey @tertle !
    I made a merge request with the 2.2.0 branch updated with lastest Entities & Collection package.
    Can you push this version also on the UPM server please ? The last available is 1.2.4
     
    tertle, lclemens and Opeth001 like this.
  16. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    Done
     
    Sylmerria and lclemens like this.
  17. pixelsplit

    pixelsplit

    Joined:
    Sep 16, 2013
    Posts:
    171
    We are evaluating upgrading to 2022.3 / ECS 1.0 currently. When we update your event system, we get a lot of compile errors. It seems like "NativeEventStream" container is missing? It is not present in "Event System" neither in "Core".

    Code (CSharp):
    1. Library\PackageCache\com.bovinelabs.event@2.2.1\BovineLabs.Event\Systems\EventConsumer.cs(144,27): error CS0246: The type or namespace name 'NativeEventStream' could not be found (are you missing a using directive or an assembly reference?)
     
  18. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,626
    It was moved to my core library (though I recently renamed it to NativeThreadStream https://gitlab.com/tertle/com.bovinelabs.core/-/tree/master/BovineLabs.Core/Collections/EventStream)

    If you upgrading from 0.51 I would suggest picking an older version of the library (even a 1.0 variation so you don't have to make code changes) and just fix any minor compile issues that were caused by Unity renaming things.
     
  19. jorrit-de-vries

    jorrit-de-vries

    Joined:
    Aug 7, 2009
    Posts:
    71
    You also might want to change "NativeEventStream" to "NativeThreadStream" using the versions as are today on gitlab.

    Edit: oops, I missed the last message...