Search Unity

Conversion Workflow is going to dig Unity down?

Discussion in 'Entity Component System' started by Deleted User, Aug 29, 2021.

  1. Deleted User

    Deleted User

    Guest

    Unity is a fairly mature engine, and as such, I'm sure it has a huge old codebase which is now hard to edit or sometimes even understand. The codebase is dominantly based on GameObject paradigm, but now, Unity switches to Entities for a way better performance and scalability. A couple of statements made by Unity:
    And then I'm opening the Conversion Workflow docs page and seeing this:
    Again,
    • "Eventually, Unity will move to a full-DOTS implementation"
    • "It is a fundamental part of DOTS, and not something temporary"
    So will it eventually move to full-DOTS? Or is it not temporary? You guys are either unaware of your own plans, or you're digging yourself down by making more and more temporary middle-position utilities between two totally different approaches. Look at the Microsoft experience, they've been leaving the old code in their systems for decades, and now they can't change pretty much anything because it turned into a dependency hell with 20yrs old codebase. You can't chase two birds with one stone.

    I'll be speaking for myself. I'm tired of hybrids, I'm tired of systems which duplicate each other. I'm afraid of uncertainty, because if you're changing your plans between two posts on your own website, how can I have a passion to learn new stuff?

    You don't show entities in hierarchy, you don't even allow to select them. Is that how you're "rebuilding the core of Unity"? People on other threads are saying that internal work on DOTS began back when Unity was on version 5. And after all these years, after the money from IPO, you're still proposing a hybrid to us? A hybrid between an old, slow, inefficient code and a new, superfast, ingeniously effective one?

    I'm not making an insult of any kind, sorry for such a long post, it's just a cry from the heart.
     
    apkdev and starikcetin like this.
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    You're miss understanding this quote
    They're talking about the internal implementations but they'll still have front facing implementations that can be with regular GameObjects.

    GameObjects won't be going away for at least 10 years (if ever); it's hardly something you have to consider anytime soon.
     
    Antypodish likes this.
  3. Deleted User

    Deleted User

    Guest

    No, I understand that they're talking about internal code. I'm just asking what makes Unity rely on GameObjects in Editor while everything works perfectly at runtime. If you can manipulate something at runtime, you can surely manipulate it in editor, you just need to write additional code for that, you don't need GameObjects. I mean, you don't need them if you're writing clean code, not if you're making a hybrid. They're rewriting every part of the engine, even transformation or parenting things, and use different wording for all of that, but why? Why do we have OnUpdate on ECS instead of Update, Translation instead of Position? And those are only basic examples.

    I know Unity engine is extremely popular and thousands of studios rely on it, but game developers are flexible people. Why doesn't Unity say like: "Hey guys, 2022 will be the last version based on GameObjects. We will provide 2 times longer LTS support for it, but starting with 2023, our engine is purely ECS because we don't want to drown in garbage. So please, learn ECS while staying on our most stable ever 2022 version, and then jump to 2023 as fast as you can cuz this is the future"?
     
    Last edited by a moderator: Aug 29, 2021
    Ruchir likes this.
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    What you are missing here is design time data is not the same as runtime data. Data is transformed from friendly formats into feature specific efficient runtime formats. This happens with pretty much every major feature area in games. Physics, rendering, animation, etc.. And every engine does this it's not unique to Unity.

    So GameObject and it's cousins are never going away. They are necessary constructs.

    There is more separation necessarily vs a C++ engine. You still have the whole transformation paradigm, and other engines have high level design time classes for stuff just like Unity does. But with Unity you have burst and native collections. And even more generally managed vs value types. So that forces more separation, less reuse of types here and there, etc..
     
  5. Deleted User

    Deleted User

    Guest

    Okay, that sounds somewhat legit, but I still don't understand one thing. When I start the playmode, I can see the component data in Inspector. It seems perfectly user-friendly to me. When I change the data via systems, it is updated and displayed correctly. I don't get which part of the process is not user friendly.
     
  6. Deleted User

    Deleted User

    Guest


    Also, aren't "design time data" and "runtime data" concepts were manually created to justify this hybrid system?
    Runtime data in memory is optimized and structured, I get it, but Unity perfectly manages to display it in user-friendly way during playmode.
     
  7. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    451
    It is impossible to do. There is a lot of applicators that have big OOP choice base, they would be left alone with such a move. Secondly DoD is not very well known paradigm and not always is necessary. For some users I would be discouraging to choose Unity. They know OOP and they just want to make a game not learn new way of coding.
     
  8. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    347
    I somewhat agree with all this. But a better approach would be a different engine i.e. "Unity ECS" and in the future discontinuity of OOP one if UT decides to do so. This new engine still can be a branch of the current Unity, and current Unity shouldn't have access to DOTS as it's confusing for many.

    I see a lot of opinions that UT cannot drop OOP and such because of accessibility. I wonder if that's not the move you NEED to do if you want to have a better engine, especially for more complicated projects. The longer I work in the game industry more I see that game dev is more than "just want to make a game" if you want something good, you need to sacrifice that effort for new tools and systems, and if you don't do that you'll end up with another crap game that foods steam or mobile platforms. So is the trade-off, so maybe UT wants to make that trade of accessibility vs. better projects.
     
    andreiagmu and apkdev like this.
  9. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    It's important to note that the GameObjects-based conversion workflow is not the same thing as "hybrid DOTS". The conversion workflow repurposes GameObjects only as a GUI for editing data (GOs don't exist at runtime), and therefore it still counts as "full DOTS" in a way. Hybrid DOTS, on the other hand, is when you are still using GameObjects at runtime.

    But with that being said, I am getting more and more worried every day about the way DOTS tries to coexist with vanilla Unity. Even if Unity manages to pull it off, the presence of multiple different "tech stacks" in the same engine makes everything way more confusing, difficult to learn, & error-prone than it should be. After working with it for over 2 years, I strongly feel that the current state of things isn't a great solution for the long term. It works, but it feels too messy. It has a learning curve that is even steeper than a brand new engine because:
    1. all the incompatible legacy stuff becomes an obstacle to learning DOTS
    2. the workflows must make heavy compromises to make sure both tech stacks are still supported.

    In short: we DO need a conversion workflow, but it would be great to have a version of the engine that has a conversion workflow specifically made for DOTS from the ground up, without piggybacking on GameObjects. We need a version of the engine where no matter what you do in your scenes/authoring, you can rest assured it'll be DOTS-compatible, and there are no traces of legacy stuff anywhere. Less potential for mistakes or confusion, and a smaller problem space.

    I am hoping the recent DOTS news hiatus is caused by Unity thinking about how to make that clean break possible
     
    Last edited: Aug 29, 2021
    Ruchir, SamOld, filod and 12 others like this.
  10. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    I think that conversion from edit time to runtime format is good for complicated objects and bad for simple one
    So conversion must be optional feature not mandatory one

    For TransformComponents Conversion is good (but old Transform component is bad candidate for source data. It is unable to use all power of ECS transform system)
    For MoveForwardComponent conversion is bad idea it create more code and more concepts for so simple logic. And if you create unique editor for this Authoring component then you need to write second editor for runtime data just to see it and debug in usable way.

    I wish Unity to Make Conversion not from old GameObject authoring to ECS but from EditTimeComponentData to RunTimeComponentData where it is necessary and make this just like it already work in ECS - just systems that react to EditTimeCD (spawn/change) and convert it to RuntimeCD
     
    Last edited: Aug 30, 2021
  11. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    353
    Unity's strong side is to be easy to learn for any, i mean ANY, IT student. C# and Unity archetecture are very friendly for newcomes, and this is why so many games written with unity. Another strong side is community, we all know about. So imagine tons of articles, guides, videos, etc about "How to do that in unity" and all of it is about GameObject based archetecture. It will be dumb to just one day throw traditional unity code approach in the trash and present new dots one, most unity's audience unfamiliar with. So the question is, how to separate those approaches but make authoring familiar for dots newcomes. The answer is mono based authoring, for example, you can have your gameobject with MeshRednerer+MeshFilter in the same state after switching your project to dots, it just will be converted to proper dots data and you see no difference in your authoring workflow.
     
  12. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    This will only be true for a handful of very rudimentary use cases (using the familiar Transform, Renderer & Collider components). For almost everything else, old knowledge doesn't really transfer. The existing GameObject tutorials won't accomplish much for DOTS users aside from misleading them, because the rules are now different in a lot of ways:
    • you can't put monobehaviours on GameObjects and expect them to work post-conversion
    • you can't put certain other built-in components (such as the mecanim "Animator") and expect them to work. DOTS's animation system will be totally different
    • you have to put your GameObjects in Subscenes
    • if you try to set up references to other components through the inspector, you can't use those at runtime
    We need a new tool that doesn't even allow us to do any of these mistakes. We must not be allowed to drag and drop a monobehaviour on a GameObject unless it is explicitly a conversion behaviour. The mecanim "Animator" component must not show up in the AddComponent popup window. The "Static" checkbox at the top of a gameObject's inspector window must be removed since it isn't used in DOTS rendering. Etc, etc... the tool must make it impossible to do anything that isn't meant for DOTS conversion. People who have been following DOTS closely for years might be aware of all of these particularities, but new users definitely won't be. Having an editor that forces you to only do things the right way would be a much more powerful learning tool than any documentation.

    Plus, if you take DOTS physics for example, the new collider/rigidbody components have options that weren't even available in the old physics engine. There are conversion systems that understand how to convert old Collider components too, but then you're missing out on all the extra options that are available in the new components, and you might not even realize that these new components exist since the old ones are already working. It would be much better if ONLY the new full-featured components were available, and the old familiar ones were discarded. That way there would only be one thing to be aware of instead of two, and everyone would be on the same page
     
    Last edited: Aug 30, 2021
    SamOld, filod, NotaNaN and 9 others like this.
  13. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    867
    I have heard people from Unity justify the conversion work flow this way. But Franky it is a cop-out in my option. Technical artists will just end up confused and programmers frustrated.
     
  14. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Why not have full DOTS WYSIWYG editor support combined with a middle of the road API that quickly allows programmers to go from GO's to GODOTS to DOTS and back the other way.

    If GOs can have and use entities and components and systems (as functions or component classes) then we could mix the two to our liking with a more managed style of OOP that uses DOTS.

    After all Data Oriented Technology Stack is just Structures of Arrays with some Helper classes that handle multi-threading and lots of boiler plate code*.

    *This is probably the biggest problem for conversion or inter-mixing OOP and DOTS as it slows programmers down and locks them into programming a certain way, making it harder to change, adapt or mix styles.

    Or remember the 80/20 rule 80% of your code will not need optimising but 20% will. If that's the case then 80% of your game could be easy to write GOs with only 20% needing to be DOTS or GODOTS depending on the level of optimisation needed.
     
    Last edited: Aug 31, 2021
  15. apkdev

    apkdev

    Joined:
    Dec 12, 2015
    Posts:
    284
    Having spent some time playing around with a couple medium-scale semi-open-world prototypes I have to admit I have my own doubts. The conversion workflow starts clunky and only gets worse. Once you get to tens of thousands of GOs, the editor slows down to a crawl no matter how high end your PC is.

    I'm not sure what possibilities for improvement there are, but frankly, the current conversion performance is very disappointing. There is parallelism but only on subscene level, which means you have to artificially divide your levels in order to wait just a minute or two in order to see/test your changes. Opening and closing subscenes takes ages. People get confused why it takes several minutes to enter play mode because the subscenes are converting. The live conversion tools are not just unusable - they're a trap that pretty much freezes the editor. Editing large subscenes is painfully slow - selecting and modifying many GOs locks up the editor with each click. Some common workflows (editor scripts, mass modification, etc) require you to open all subscenes for editing, the thought of which induces a literal feeling of dread. I want my iteration loop back.

    (Hope I'm not being too rough - I'm very optimistic about DOTS overall)

    I hope that I'm overlooking a larger plan that involves ditching GOs in favor of an ECS-native conversion workflow. Now that I think about it, it seems like the obvious way forward. First develop a solid runtime, then entirely swap out the authoring workflow. If that's the plan then that's actually a pretty genius way to spread out the engine upgrade effort across time.
     
    Last edited: Sep 5, 2021
    Ruchir, Lukas_Kastern and JesOb like this.
  16. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    For the editor to be fast it needs to save data on a fairly granular level. But right now everything is being forced to work with what the runtime wants, and the two things have different needs. So design time it all just scales horribly.

    By what the runtime wants I mostly mean all of the final arrays. While design time you want to be able to save at the individual component level if needed.

    Sub scenes appear to be an attempt to brute force a single storage format to work. By offloading the work to another process. But better solutions are easy to see. So it's hard to tell what their long term thinking is here.
     
  17. Chris-Herold

    Chris-Herold

    Joined:
    Nov 14, 2011
    Posts:
    116
    The conversion workflow is a mistake and Unity needs to wake up and correct it.
    Unreal 5 is about to swallow a big chunk of the market and Unity will - without a doubt - be on the losing end of that if they don't get their act together.

    There are too many teams/projects that are incompatible with each other (UI Toolkit not compatible with new input system, just to give one glaring example).
    Things are progressing at a snails pace (URP) and the average user must be utterly confused what to do - where to start - what to use - what to expect.
    It is time to bring all these seemingly separate pieces together. In fact it is long overdue.

    Have i mentioned the package manager and everything about package management is a huge mess? Also constant regression bugs and big performance degradations from version to version.
    This needs to change - quickly.

    DOTS needs to have proper authoring tools - without GameObjects.
    Why is DOTS Visual Scripting a priority while proper authoring tools are not?
    These kind of upside down decisions make no sense.
    Perhaps a change of management is in order.
     
    Last edited: Sep 5, 2021
  18. rauiz

    rauiz

    Joined:
    Mar 19, 2013
    Posts:
    43
    I agree that the conversion workflow, as it currently stands, is a bit bloated and confusing. It is also assumption heavy, blocking certain types of projects from even using it. That being said, the general idea of conversion from authoring to runtime data is very good. I've been rolling my own authoring tool for fighting game character states by doing some timeline customization and then parsing that data into runtime formats. Not only it is a cleaner codebase for it, it is significantly more flexible. Also, it allows us to deliver authoring tools with better usability for designers/tech artists without actually having to complicate our run-time system logic. So I encourage anyone that hasn't tried this type of workflow, to at least test it out :D

    Imho though, the biggest problem with DOTS right now is that it is over-focused on ECS. I'd love to see things built differently, with ECS being an optional layer on top of the rest of DOTS that we get to opt-into when the project calls for it, but avoid it when it is not worth the hassle. This seems to be coming from what to me is a misguided attempt to make proper memory management and concurrency as "easy" and "accessible" as the MonoBehaviour flows. The memory management part is probably doable, but concurrency is inherently complex and context-dependent --- and will require people to actually understand multi-threading/job system to use correctly (TLDR: I don't think tying DOTS to ECS, as heavily as it is, is a good thing).

    Just some examples:
    • I'd much rather have a Job Graph visualization tool (that gets data out from unity's scheduler in a run) that allows me to see how unity's scheduler is visualizing the dependency graph than having that ECS System's window (especially since it worked poorly with multiple worlds the last time I tried --- not sure if support for this improved).
    • I'd much rather have more Job-compatible APIs such as the new nav-mesh and TransformAccessArray stuff so that I can create project specific solutions with the correct level of granularity than forcing myself to use ECS for API compatibility or Editor usability stuff even when the project is not a good fit for it.
    • I'd much rather have the allocators described here (How to survive without smart pointers?) than I would having more syntatic sugar for writing multi-threaded code.
    In general, NativeCollections, BlobAssets, JobSystem and Burst are great pieces of tech and ECS seems to be holding them back a bit due to the requirement of making them "hyper-accessible". That being said I'm confident Unity will turn this around eventually (they hired some very experienced people for this :)). I'm just hoping the ECS part of DOTS doesn't keep slowing down the other great parts of the stack as they sort out this hyper-accessibility thing.

    On a side note, I think that the JobSystem (even with the boilerplate) is already very accessible and very simple to use correctly --- even without ECS magical system dependency ordering to take care of that stuff for you --- you just need to understand concurrency (that JobGraph visualization tool would probably help people a lot in their quest to understand it :rolleyes:).
     
    skiplist and apkdev like this.
  19. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    Could Unity give us a lot of the power of their systems with ECS/Burts/Jobs via simpler APIs or WYSYWIG components?

    For instance the power of Draw Mesh Instance could be simplified into a Component or Mesh Renderer setting.

    The idea being that 80% of the time a simple to use but powerful system will work and the other 20% of the time more complex and advanced APIs and DOTS systems could be used.

    With a DOTS approach they could even just generate template systems that appear as components but can be modified and changed by more technical users.
     
  20. rauiz

    rauiz

    Joined:
    Mar 19, 2013
    Posts:
    43
    Basically, I don't think ECS should be an entire new workflow --- just a tool you use for certain types of projects or even just parts of a project. I think it fits better that way. As an example, I've implemented GGPO variants using ECS and not using ECS and I can definitely tell you it wasn't worth the trouble of trying to fit ECS into it. The version I currently have here is Jobified and Bursted (where applicable) and it is significantly simpler to maintain. The same is true for my special move detection stuff (which is fully data-oriented, bursted, SIMD-ized and Jobified). Some problems just don't benefit from the ECS forced paradigm and attempting to shoe-horn it in will just get in the way of you actually doing what you want :eek:.

    To be clear, I'm not a big OOP-person (in fact, I think it gets more in the way than it helps in a way that is even worse than Unity's ECS). I just don't think replacing an OOP-dogmatic approach with an ECS-dogmatic approach is that much better. I'd prefer Unity provided APIs and tools (JobGraph Visualizer -- which would be good both for ECS and for non-ECS projs, WYSYWIG editors, offline/online conversion tools from Scriptable Objects, etc...) that'd make it easier to make project-specific workflows and tech and leave the "one-size-fits all ECS approach" behind :D.

    Take Unity DOTS Physics, for example. It says it's core algorithms are meant to be decoupled from ECS and Jobs. That is great and we should have more of that. However, most if not all of its docs, are tailored towards using it with the Unity's ECS implementation. I think that is a mistake. Tell us how to use the Job-compatible APIs independent from ECS first, that way we get the flexibility for project-specific use cases first. Then, tell us how to integrate that with ECS. Trying to do this the other way around seems counter-productive to me, as I'll have to understand both the system as well as its ECS integration at the same time --- making it confusing and hard to know which parts are ECS-independent and which aren't :( It is hard to know, though, how much of this is a documentation and communication problem and how much is it a system design problem...
     
  21. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Thing is, as a moderator and someone around here pretty much daily for 10+ years, I can tell you hand on heart that half of those resources ALREADY don't work, regardless of DOTS. So really all that matters is that Unity absolutely focus on the docs that are available online. Can't rely on tutorials and video stuff by third parties, even now. DOTS has nothing to do with this problem. It's a natural issue in software development.

    The only real solution for that is to increase the value of the live docs IMHO.
     
    JesOb likes this.
  22. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Even though I haven't tested it in practice, I do feel like OOP and ECS can coexist peacefully in the current state of DOTS. And I think it's easier to bring OOP into DOTS than it is to bring ECS into gameObjects/Monobehaviours

    In theory, with Managed IComponentDatas that can contain class types, you can do anything you'd be able to do in OOP, but have it live on an Entity. Simply have code that executes on the main thread, and (for example) calls polymorphic functions on classes that are stored inside these managed components. You can also use the main thread EntityManager in this OOP context to get ECS components like Colliders and whatnot, and do physics queries with the ECS PhysicsWorld, etc....

    I would imagine, for instance, a "StateMachineComponent" IComponentData class that holds a List<State>. "State" would be an abstract class with an overridable Update() function, and "StateMachineComponent" would have an Update() function that calls Update() on the active "State". So a system would iterate on all entities that have "StateMachineComponent" on the main thread, and then go call "stateMachineComponent.Update()" on each of them. And that system could also handle writing back pertinent data from the stateMachine update to an unmanaged component, so that it can be readable from bursted jobs later

    But like I said, I've never actually tried this, so I don't know if this would really work as I imagine it. I'd be curious to hear about people who tried doing that in practice, and see if it worked well for them.
     
    Last edited: Sep 6, 2021
    NotaNaN and apkdev like this.
  23. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,270
    To properly decouple any codebase from the architecture, you need to make it an immediate API. Not immediate in the sense that it can't be asynchronous using jobs and the like, but immediate in that nothing runs automatically. Coupling the codebase to the architecture allows Unity to make things work without the user having to write any code. Unity Physics is like this. You can add components in the editor, press play, and watch them fall and collide with each other. But when you want to customize things, there's a lot of dragons and some stuff is straight up impossible. Immediate APIs are the opposite. They never work out-of-the-box. The user always has to write some setup code for them. But then the user gets a lot more control and customizability.
    My understanding is that different engine teams responsible for individual features are responsible for adding these GameObject-based performance APIs, not the DOTS team that is doing ECS stuff.
     
  24. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Just did a little proof of concept to follow up on this:
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using Unity.Entities;
    4. using Unity.Mathematics;
    5. using UnityEngine;
    6.  
    7. [DisallowMultipleComponent]
    8. public class OOPTestAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    9. {
    10.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    11.     {
    12.         BehaviourComponent b = new BehaviourComponent();
    13.         b.Behaviours = new List<TestBehaviour>();
    14.         b.Behaviours.Add(new BehaviourA());
    15.         b.Behaviours.Add(new BehaviourC());
    16.  
    17.         dstManager.AddComponentObject(entity, b);
    18.     }
    19. }
    20.  
    21. [Serializable]
    22. public class BehaviourComponent : IComponentData
    23. {
    24.     public List<TestBehaviour> Behaviours;
    25.  
    26.     public void Update(EntityManager entityManager, Entity selfEntity)
    27.     {
    28.         foreach (var b in Behaviours)
    29.         {
    30.             b.Update(entityManager, selfEntity);
    31.         }
    32.     }
    33. }
    34.  
    35. public class OOPTestSystem : SystemBase
    36. {
    37.     protected override void OnUpdate()
    38.     {
    39.         Entities
    40.             .WithoutBurst()
    41.             .WithStructuralChanges()
    42.             .ForEach((Entity entity, BehaviourComponent behaviour) =>
    43.             {
    44.                 behaviour.Update(EntityManager, entity);
    45.             }).Run();
    46.     }
    47. }
    48.  
    49. public abstract class TestBehaviour
    50. {
    51.     public abstract void Update(EntityManager entityManager, Entity selfEntity);
    52. }
    53.  
    54. public class BehaviourA : TestBehaviour
    55. {
    56.     public override void Update(EntityManager entityManager, Entity selfEntity)
    57.     {
    58.         Debug.Log("A");
    59.     }
    60. }
    61.  
    62. public class BehaviourB : TestBehaviour
    63. {
    64.     public override void Update(EntityManager entityManager, Entity selfEntity)
    65.     {
    66.         Debug.Log("B");
    67.     }
    68. }
    69.  
    70. public class BehaviourC : TestBehaviour
    71. {
    72.     public override void Update(EntityManager entityManager, Entity selfEntity)
    73.     {
    74.         Debug.Log("C");
    75.     }
    76. }

    This demonstrates creating a "BehaviourComponent" class-based component that lives on an entity, and holds a list of polymorphic behaviours to update.
    • OOPTestAuthoring is an authoring component that adds the managed component to the entity, and adds polymorphic behaviours to that component's list of behaviours
    • BehaviourComponent is the managed component that holds behaviours and updates them one by one when its Update() function is called
    • OOPTestSystem is a system that calls Update() on all BehaviourComponent
    • TestBehaviour is an abstract class that can be inherited from to create specific behaviours, such as BehaviourA, BehaviourB, BehaviourC
    All behaviour updates are passed an EntityManager and their own entity as parameters, so they can read/write anything in the ECS during their Update(). They could also be passed the PhysicsWorld as parameter and do physics queries in their Update(). When I press play, this prints "A" and "C" constantly in the console, since the authoring component adds only the behaviours A and C to the list of behaviours

    What I like about this is that even though we are doing something that is heavily OOP, everything in our game is still just defined as Entities, Components, and Systems. Everything is still coherent and playing by the same rules. If we did a mix of GameObjects/Monobehaviours + ECS stuff on the side, we'd have two different "architectures" going on in our project at the same time. This would create confusion and difficulties for communication between the two worlds
     
    Last edited: Sep 6, 2021
    bb8_1, Bivens32, Occuros and 3 others like this.
  25. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    867
    Until Burst supports managed objects I think OOP is pure poison for your code base. Not because it is bad but rather because it just does not work.
     
  26. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Can't be worse than doing it in monobehaviour, no? I specified this is done on main thread
     
  27. TheOtherMonarch

    TheOtherMonarch

    Joined:
    Jul 28, 2012
    Posts:
    867
    I think it would be worse because you already recoded everything. You just need to suck it up and think harder and deal with having more convoluted but simpler code. Stop trying to cram everything into one magical update. Nothing you are trying to do is that hard to replicate in Burst.

    Also it has nothing to do with the conversion workflow.
     
    Last edited: Sep 7, 2021
  28. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    There is such a thing as types of problems where the usual ECS approaches will be less efficient than an OOP-style approach.

    For example: creating an ordered events system where there can be dozens of different event types, which can read/write a wide variety of data types

    ECS is good when you can batch a large amount of similar operations together, but bad when you need to alternate between lots of different kinds of operations at a high frequency. In the case of DOTS, it's also bad when you end up needing high-frequency structural changes, or if you'd have so many different kinds of operations in your game that you'd need to schedule 1000s of different jobs to make it possible, and the scheduling cost alone would kill your performance.

    So the solution in those cases is to either do main thread OOP, or "pseudo polymorphism" inside a job using a switch case. The end goal being to either reduce the total job count needed, or eliminate the need for structural changes when you have to perform a certain sequence of different steps

    Here's an example that demonstrates the performance advantage: https://forum.unity.com/threads/sources-available-dots-polymorphic-components.1132123/#post-7287379
     
    Last edited: Sep 7, 2021
    JesOb, rauiz, apkdev and 1 other person like this.
  29. rauiz

    rauiz

    Joined:
    Mar 19, 2013
    Posts:
    43
    While I don't know enough about the ECS-based implementation you propose here to give any specific feedback on it, I definitely agree the "discriminated union/pseudo-polymorphism" approach is a good way of solving this low-data-volume/high-data-type-variance problem within DOTS. I'm using it myself for a couple of things in one of my projects, though mine is not ECS-based (just using the rest of DOTS). You get to use jobs, burst and, all you really end up with code-wise is a simple switch case most people can wrap their heads around.

    Back to the conversion flow topic, I generally agree that it has some problems:
    • Confusing UX due to not all features available in MonoBehaviour being supported (and vice/versa) -- on a side note, naming of old components all make them seem like they'll actively do things, which doesn't help new devs understand the whole authoring vs runtime idea.
    • Poor editor support for multiple worlds and granular conversion (again this may be a documentation problem).
    Not sure how where I'd look to solve these problems, but I tend to agree that specific authoring tools for the ECS-stuff would probably yield better results (at the very least on the UX side of things), especially if that would allow for first-class support (and docs) to working with multiple worlds which is often a very useful tool.
     
  30. Krajca

    Krajca

    Joined:
    May 6, 2014
    Posts:
    347
    I wonder if the infamous "disabled components" announced by Jonathan here on the forum will fix just that. You should be able to change behavior without structural changes.
     
  31. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    OK why can't we have the speed and performance of DOTS with the the Object coherence* of OOP?

    IMHO DOTS is just a function/method call as a System and Entities are just SOA parameters passed to the function.

    What if there were some square bracket compilation tricks that we could add to our OOP designs that would convert functions to systems e.g. [DOTS_System] <Function>.

    After all our code is just TOKENS to the compiler/parser and we should always be aiming to make it as easy as possible to code the things we want our programs to do.

    *Coherence - I think OOP design helps group things and break up our problem domains into manageable chunks that make solving problems easier. DOTS is a step backwards in this regard as it works on finer grained functional elements and data blocks losing coherence. It also generates a ton of boiler plate code that means you end up writing a page of code for a one line function call. ​

    In addition if you start with OOP and profile to find where you need DOTS it is then a really tedious process to convert OOP code to DOTS when it should be as simple as possible to convert a OOP method to a DOTS system, IMHO.
     
  32. rauiz

    rauiz

    Joined:
    Mar 19, 2013
    Posts:
    43
    We can, to a certain extent. That being said I definitely don't agree with the "DOTS being just SOA-taking functions as systems". The foundations of it come from Data-Oriented Design -- which, imho, is much more related to data-access patterns (when you read/write to which data), fitting that to how hardware actually works and not making things more complex than what they are. Sometimes, if SOA is actually making something more complicated than what it needs to be, just write it in a different way keeping in mind the data-access patterns (which is the most important aspect of DoD when it comes to code-maintainability). Thinking like this makes problems decoupled, from a data perspective (which is what actually matters) instead of a code perspective, which in turn allows for easier and better concurrency and makes things optimizable. Also, code can now be read as a series of data transformations that explain clearly what the input/output/latency is (increasing on-boarding speed of team members and overall maintainability).

    Imho, OOP often gets people asking the wrong questions -- that aren't data related, but code related -- and usually adds very little value: "Does the character take damage or does the ability deal damage?", being a classic example of a philosophical and highly subjective discussion that is irrelevant and only originates because behavior (functions/methods) arbitrarily MUST be tied to a class (data structure). That's not to say OOP isn't a good tool in understanding separate domains and types of problems you have. It's just that, in my experience, I've yet to see a real advantage to using OOP directly in code that is not overshadowed by the problems it introduces. If you try to map your code to interpretations of the model of the world, it gets harder to scale (as you need everyone to agree on an interpretation -- which is very dependent on individual past experiences), harder to maintain (since code is now organized around high-level domain-specific concepts instead of real data-access patterns) and close to impossible to parallelize (since system calls will often not work in batches and have immediate latency due to the nature of thinking of individual world objects doing things in the world).

    This doesn't really have anything to do with the main topic of thread, so I won't keep discussing this here as to not derail OP's discussion. Feel free to send me a message if you'd like --- I enjoy these "OOP+DOD+InsertRandomParadigmHere" discussions and have some real world examples of my experience with this that could be fun to discuss :D

    PS: I agree that boilerplate is annoying and we can do without it so long as we don't introduce a lot of complexity in order to avoid it. In that vein, there are low-cost ways you can minimize the impact of it: IDE Code Snippets, code-gen (for certain types of problems it is actually a great tool), etc... And it is not a problem exclusive to DOTS (Analytic code -- for data validation -- and/or UI -- in Unity -- often have a lot of boilerplate stuff as well).
     
  33. JesOb

    JesOb

    Joined:
    Sep 3, 2012
    Posts:
    1,109
    For this issue see:
    https://forum.unity.com/threads/bevy-vs-unity-dots.1156052/#post-7416611
    https://forum.unity.com/threads/bevy-vs-unity-dots.1156052/#post-7417796
     
    Last edited: Sep 8, 2021
    andreiagmu and apkdev like this.