Search Unity

[Source Code] DotsUI - open source UI framework for DOTS

Discussion in 'Entity Component System' started by supron, Jul 24, 2019.

  1. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    This is the first release of the DOTS UI system (https://forum.unity.com/threads/showcase-pure-dots-ui-system-detailed-description-feedback.688531). The source code is released under MIT license, so you can do anything you want with it. It's still very early development stage so don't be disappointed with lack of features and bugs. Remember, it started as a learning project and some parts of code are very ugly (strange class names, etc.).

    Link to the repository:
    https://github.com/supron54321/DotsUI

    I'd really like work full time on this project, but right now I can spend only 1-2 hours per day. That's why it took almost 2 months to publish this project, after my first post. I have rewritten the core from scratch a few times. Now I really like current design. It's fast, multithreaded and can be easily extended with new primitives and high-level controls.
    There is still A LOT of work to do before it will be production-ready. Check list of known issues and roadmap.

    Because of bugs in ConvertToEntity, the system is completely detached from this workflow and uses its own converters. In this version, the only "easy" way to work on UI is to convert Canvas hierarchy and prefabs through classes in DotsUI.Hybrid namespace. There is no high-level API for spawning pure UI Entities. I strongly recommend to convert unity prefabs to DotsUIPrefab and instantiate them form systems. Breaking changes in the core are pushed in almost every commit.

    Canvas render-mode must be set to "Screen-space camera". Conversion pipeline automatically adds a component to the camera (OnRenderImage hook).

    Design

    DotsUI is trying to convert UnityEngine.UI hierarchy to pure DOTS representation. Due to performance reasons, I removed rotation from RectTransform component. Scale will be implemented in future releases. The whole system is designed to achieve the best possible performance, but there is still room to make improvements (remove sync points, more jobs, and better data layout).

    Samples

    Documentation is not ready yet. You can check "PrefabExample" to learn how to create and instantiate DotsUI prefabs:
    https://github.com/supron54321/Dots...i.hybrid-samples/DotsUI.Samples/PrefabExample

    Contribution

    Right now I'm looking for the feedback. Share your thoughts about the idea of open source UI system. Once I finish the core, we can start with pull requests from the community.
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,255
    I think you should consider using the built-in conversion system. One thing I discovered relatively recently is that if Entities.ForEach doesn't let you do what you want to do, you can usually get around it by making an EntityQuery of the types you want and then getting the array of Entities from that. It's not as fast, but it might let you temporarily get around the RectTransform issue until the next Entities release.

    I do weekend game jams to build and battle-test my custom tech stack built on top of DOTS. If you can get this UI working with Unity's GameObject Conversion, I'd be more than happy to give you some battle-tested feedback!
     
  3. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    I will once issues with RectTransform are resolved. I implemented my own converters only because I needed anything to test UnityEngine.UI -> DOTS conversion.

    Still a lot of work to do, before its "battle-ready" :D
     
  4. Deleted User

    Deleted User

    Guest

    I want to thank you for your awesome work. It's definitely something that I will be using in my future games.
     
  5. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    676
    Great job. Will have a look at it as soon as I'll be on a computer.
    I'm mostly looking for UI Text but by looking at the GitHub repo it doesn't seem to be available yet.

    Anyway thanks for this.
     
  6. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    Text is supported through text mesh pro component and fonts. Currently, "master" branch supports conversions from the following UI components:

    * Image
    * TextMeshProUGUI (SDF fonts, not all features are supported)
    * TMP_InputField (very simple implementation)
    * Selectable
    * Button
    * RectMask2D
    * CanvasScaler

    On develop branch I'm working on ScrollRect implementation.

    Unfortunately, ConvertToEntity is still not implemented. I encountered a critical bug in the conversion pipeline. I hope Unity devs can fix it soon. Right now the only way to convert Canvas hierarchy is to call RectTransformConversionUtils.ConvertCanvasHierarchy(Canvas, EntityManager).

    DotsUI works with unity 2019.3.0a8+. Hybrid UI renderer requires new Mesh API from 2019.3 (it's 2-3x faster).
     
    Deleted User and GilCat like this.
  7. Deleted User

    Deleted User

    Guest

    @supron what kind of events does your UI support? (PointerDown, PointerUp, PointerClick, etc)
     
  8. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    • Down
    • Up
    • Click,
    • Enter
    • Exit
    • Selected
    • Deselected
    On develop branch I added support for:
    • BeginDrag
    • Drag
    • EndDrag
    • Drop
    I'll merge branches by the end of this week.

    Few words about low-level events (raw pointer and keyboard events). I considered different approaches for event handling. In early DotsUI development, I implemented events as components added to the target entity. That wasn't a bad idea, but it had few drawbacks. The first problem: it required entity data relocation and archetype change. Not bad if you have rare events like click or selection. Worse if you have a lot of frequently updated events (OnDrag, OnEnter+OnExit). The second problem: it required event queue cleanup at the end of the frame (another relocation). In the current DotsUI version, I implemented events as separated entities. Event entity archetype is very simple. It has PointerEvent component (with target entity) and PointerInputBuffer (dynamic buffer with eventID, eventType and eventData). This approach requires additional filtering job before per-target event handling, but it's very very fast (burst compiled) and avoids archetype changing. I even made a dedicated component system for auto target filtering.

    High-level events (ButtonClickedEvent, InputFieldReturnEvent, InputFieldEndEditEvent) are still components added to target entities. I'll probably leave it like this because high-level events must be easy to use and filter (simple entity query over typeof(MyButton), typeof(ButtonClickedEvent)). Overhead is minimal because these events are rare. Example usage: https://github.com/supron54321/Dots....Samples/PrefabExample/InstantiationSystem.cs
     
    GilCat likes this.
  9. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    New version merged on GitHub. Changelog:

    [0.2.0] - 2019-08-19

    Added

    * Added drag & drop support
    * Added ScrollRect

    Changes

    * Removed custom parent system. Now DotsUI uses Unity.Transforms
    * Updated entities packages
    * Updated obsolete API
    * Unit tests upgraded to latest changes in the core
    * Minor performance improvements
    * Updated roadmap
    * LegacyRenderSystem renamed to HybridRenderSystem
    * Improved idle performance of HybridRenderSystem (added RequireForUpdate EntityQuery)

    Fixes

    * Fixed issue with last few triangles not being rendered after InputField lost focus
    * Renamed folders in DotsUI.Hybrid
    * Removed unnecessary sync point in button system
    * Fixed exception in selectable system caused by NativeHashmap being overfilled
    * Fixed issue with canvas not being properly rebuilt after camera size changed
    * Canvas pixel size is now properly taken from camera size (instead of screen size)
    * Pointer events are now properly stopped from being propagated to parents


    ScrollRect doesn't support all of UnityEngine.UI features. It works only in one direction (Left->Right &? Bottom->Top), and it doesn't support scroll bar hiding. DotsUI doesn't support mouse scroll yet, so it's obvious it doesn't work in ScrollRect.


    [0.3.0] - 2019-09-08

    Added

    * Added support for ConvertToEntity
    * Added support for Screen Space - Overlay canvas rendering mode
     
    Last edited: Sep 8, 2019
    YurySedyakin, tanohmz, GilCat and 4 others like this.
  10. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Hello,
    I've tried to convert a very simple scene from Unity UI to DotsUI. The setup is extremely simple - just a canvas with an image as a child object. The whole thing works when there is ConvertToEntity on Canvas game object. But I tried converting the Canvas into a subscene. At this point it broke. Not entirely, but it fails to convert the sprite asset. I've looked into the source a little bit, looks like you are adding sprites into destination entity manager using
    Code (CSharp):
    1. DstEntityManager.CreateEntity(typeof(SpriteAsset), typeof(SpriteVertexData));
    Instead, I believe you are supposed to use
    Code (CSharp):
    1. GameObjectConversionSystem.DeclareReferencedAsset(sprite);
    For this it looks like you need an additional system that updates in GameObjectDeclareReferencedObjectsGroup, and also you need to then convert declared sprite assets by their own conversion system. Anyway, I'm pretty new to this convertion workflow so I wasn't able to make it all work.

    Also it looks like DeclareReferencedAsset already adds a component object with the Sprite to the entity, so I guess you don't need SpriteAsset shared component at all.
     
    Last edited: Sep 17, 2019
  11. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Ok, I managed to fix Image conversion to work with subscenes. Added a system that declares referenced assets (Sprites) and another system that converts those declared sprite asset references by adding SpriteAsset shared component and also SpriteVertexData. For the whole thing to work I had to also create SpriteAssetProxy, make it [System.Serializable] and also make SpriteAsset [System.Serializable].
    Next: have to apply a similar fix to TextMeshPro font assets.
    And then: figure out if we can work without SpriteAsset shared component altogether, cause Sprite asset entity already has the Sprite component object. This isn't trivial because SpriteAssets being shared component gets addressed by shared component index later down the pipeline and my understanding is component objects are NOT shared components.

    Update: I managed to fix TextMeshProUGUI conversion to also work with subscenes, the whole thing works with subscenes now. I can provide the source code of the changes I made if needed.
     
    Last edited: Sep 18, 2019
    supron and psuong like this.
  12. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    Good job! Can you create a pull request with your changes?

    SCDs are quite useful in optimization. I can use indices to batch similar materials in the job. Of course, it could be done without them.

    Btw. I have a little break from this project. I'll start commiting new features after the weekend.
     
    psuong likes this.
  13. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    supron likes this.
  14. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    I wonder what the DOTs team make of this. Would they want to follow the same approach or are they doing something completely different?
     
  15. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Now as DotsUI works with subscenes I'd suggest to think about making some/all systems [ExecuteAlways] so that when a subscene is in closed state one can still see the converted UI.
     
  16. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    I already started it. I have some problems with RectTransformSystem (unity freezes) but I'm looking what causes this issue. The only problem I see at the moment is that screen space overlay, requires a dummy object to execute command buffer on GUI repaint event. I made some changes in code to create and destroy this object, but I'm looking for a more suitable solution. Unfortunately, Unity doesn't expose API to hook into GUI repaint without GameObject.
     
    YurySedyakin likes this.
  17. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    One more observation: for the canvas to be rebuilt one has to add DirtyElementComponent flag components. I wonder if the logic behind this could be reversed and instead of DirtyElementComponent flag there would be NonDirtyElementComponent flag that the system sets by itself. Then all entities without said flag would be considered dirty. This way you could eliminate the need for manual setting of dirty flag.
     
  18. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Got a problem that looks quite serious to me. Unity UI has well defined draw order that is based on hierarchy tree. Now the hierarchy itself is preserved when converting to entities, but sibling order is not (as it seems). So images and texts are drawn out-of-order. I guess it was a bad idea to base draw order on hierarchy in the first place. But I don't see how to fix ordering in DotsUI, I guess we need ideas beyond what Unity UI can provide.
     
  19. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    @supron A question: how do I show/hide parts of the UI. Like in GameObject world I'd do SetActive(true/false), what's the equivalent action in DotsUI? Do I have to actually destroy entities? Or can I flag them (preferably whole hierarchies) to not be rendered?
    Edit: figured it out myself - there is that Disabled component from Unity.Entities
     
    Last edited: Oct 9, 2019
    supron likes this.
  20. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    [0.4.0] - 2019-08-19

    Known issues

    * Screen space overlay canvas throws exception in closed subscene

    Added

    * Slider control
    * DotsUI inspector window (now displays only UI mesh info)

    Changes

    * Removed old conversion pipeline
    * Refactored GO->Entity conversion code


    Fixes

    * Fixed sibling order after GO->Entity conversion



    It turned out to be hard task, because I couldn't hook renderer properly. Screen space overlay requires additional GameObject to capture GUI render event. I'm still thinking about solution.


    DirtyElement flag is a very efficient way to invalidate canvas hierarchy. We don't want to rebuild hierarchy every frame. The only problem with the current design is a lack of high level API which could automatically invalidate element when any value was changed. I'm thinking about implementing such API for easier UI control.

    Hierarchy order is very simple and straightforward approach. DotsUI uses the same principles, but ConvertToEntity destroys siblings order. I already fixed that issue in 0.4.0 by forcing DynamicBuffer<Child> to preserve hierarchy order. It seems like a good solution.
     
  21. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    I am continuously getting this in the editor:
    InvalidOperationException: The following game object is invoking the DontDestroyOnLoad method: ScreenSpaceOverlayGUIProxy_DO_NOT_DESTROY. Notice that DontDestroyOnLoad can only be used in play mode and, as such, cannot be part of an editor script.

    Also com.dotsui.core depends on com.dotsui.hybrid (using DotsUI.Hybrid in DotsUIInspector.cs) which looks wrong to me.

    And I can't understand the reasons behind this warning: Ignoring invalid [UpdateAfter] attribute on DotsUI.Core.BeforeRectTransformUpdateGroup because DotsUI.Core.UserInputSystemGroup belongs to a different ComponentSystemGroup. Doesn't make sense because both mentioned groups have UpdateInGroup(typeof(SimulationSystemGroup)).
     
    Last edited: Nov 7, 2019
  22. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    I fixed that issue on develop branch. I also implemented proper subscene rendering with SRP. It works without SRP if you manually create GameObject with "ImguiProxy" Component. I will release hotfix soon.
    It's a bug. I'll fix it too.
     
    YurySedyakin likes this.
  23. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    63
    Getting error when trying to spawn a prefab with text in it. Works well without text. Here it is:

    IndexOutOfRangeException: Index 0 is out of range of '0' Length.
    Unity.Collections.NativeArray`1[T].FailOutOfRangeError (System.Int32 index) (at <4e781ea27afa4779b4c4bcd46aeba67a>:0)
    Unity.Collections.NativeArray`1[T].CheckElementReadAccess (System.Int32 index) (at <4e781ea27afa4779b4c4bcd46aeba67a>:0)
    Unity.Collections.NativeArray`1[T].get_Item (System.Int32 index) (at <4e781ea27afa4779b4c4bcd46aeba67a>:0)
    DotsUI.Core.TextMeshBuildSystem+TextChunkBuilder.Execute (Unity.Entities.ArchetypeChunk chunk, System.Int32 chunkIndex, System.Int32 firstEntityIndex) (at C:/work/github.com/U1001975/DotsUI/com.dotsui.core/DotsUI.Core/TextMeshBuildSystem.cs:83)
     
  24. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,939
    Hi there,

    Is it still in development?

    Thanks
     
  25. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    Hi. Not really. There are few reasons.

    1. I do not have enough time.
    2. Constantly updated Dots package and unstable editor makes it hard to develop and maintain.
    3. I do not see potential in this kind of UI system. In my opinion, UI Elements will be superior compared to any other UI solution. UIE has extremely efficient renderer and flexible layout system. While it's not ready for runtime and DOTS, it will eventually replace all existing UI frameworks. Making anything else is pointless and just waste of time. However, UIE is a large framework so pure DOTS UI is probably a good idea for Tiny runtime. That's something I'd love to try.

    So... I'm not killing this project yet. I have some great ideas I'd really like to implement. I already started some experiments with new acceleration structure for fast layout update and pointer collision checks. It has good potential for Tiny UI. Unfortunately Tiny does not support any CommandBuffer-like system for custom rendering and I cannot really test it in pure DOTS environment. But that is not the real problem. Lack of free time is.
     
    SolidAlloy, bb8_1, jiaweif3 and 5 others like this.
  26. cultureulterior

    cultureulterior

    Joined:
    Mar 15, 2015
    Posts:
    68
    Thank you for your hard work - If I wanted to extract just the text rendering elements of this (for using with worldspace text rendering), which bits would I need?