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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Keeping track and differentiating with previous data in DoD

Discussion in 'Entity Component System' started by 5argon, Nov 7, 2018.

  1. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,554
    Recently I started using data oriented design on UI. The appearance of UI depends solely on one IComponentData on UI entity. The UI changes only if chunk's changed flag was set. (That is, I have .SetFilterChanged on my component group so that its length is always 0 if nothing changed)

    Screenshot 2018-11-05 10.59.19.png

    Imagine I have a component with :

    Page page;
    int selectedIndex;
    BlittableBool showing;

    When I change the page enum it would animate switch page.
    In each page there is a selectable menu. selectedIndex specified which one is highlighted right now.
    If showing is false then the page is invisible regardless of all other fields.

    Outside source like buttons would change this data via ComponentDataWrapper (switch page buttons at bottom edge would change `page`, corner button would set `showing = false` and so on)

    The wrapper will sync the data to Entity, and I can see the UI change accordingly. It works when changing public fields in the inspector too.

    The problem is when I change only selectedIndex, it would animate to the same page again before updating the highlight, because changed filter cannot detect which field changed. Is this a nature of DoD?

    I guess the solution to this is that I would need a complete copy of previous change available at all time, so that when it detect changes I can compare with previous copy if the field really changes or not. The question is, is this the right approach or any smarter way? Any suggestion/methodology to do this book keeping efficiently? (I guess, programmer with React experience might know something useful?)

    Edit : From https://redux.js.org/faq/storesetup...dispatched-action-as-part-of-the-subscription it give me some idea that if I could also get the action that triggers the change, then I could infer the previous state without actually seeing the complete previous state. (e.g. page change/back button press/selected change + the current state is enough to say if we should play the switch page animation or not) But Redux says knowing the action in addition to the current state is a hack around this paradigm.
     
    Last edited: Nov 7, 2018
  2. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    Another option would be to extract SelectedIndex in to its own ComponentData type. Then you can detect changes between the SelectedIndex component, and the Page, Showing component.
     
    5argon and Vacummus like this.
  3. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    ^ I think that's good solution and also keeps your ComponentData small which is good for your cache.

    I am front end dev who works with React and Redux, and I would not recommend looking into those two on how to do data oriented UI development. React is (for the most part) a functional programming UI library, were UI components are functions. In DOD, UI components are data. In React, the code is smart. In DOD, the data is smart and the code is dumb. Completely different paradigm.

    Redux is a global state store that solves the problem of React components updating global state. The reason it has to solve for that problem is because of immutability and smart code. DOD does not need to solve for that problem because it does not need immutability since your code is flat, dumb, and global (thus no side effects). In other words, the ECS systems are like reducers but without actions and dispatchers (which again is smart code).

    But I wish Facebook would drop FP and go down the DOD route with React. React is currently plagued with accidentally complexity and performance issues due to immutability and smart code.
     
    5argon likes this.
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,554
    I looked up Redux/Flux UI programming a bit, to have the UI truly a representation of the current data state the data state would have to store each buttons position, alpha, etc. as it animates in and out. Or at least store the animation's current time. But in reality we don't want to play animation by varying the animation time in data. Just for animation (and other niche things like playing audio) that we want it to be one-offs, which unfortunately conflict with DoD.

    (Or "previous state" approach : https://medium.com/flutter-io/animation-management-with-flutter-and-flux-redux-94729e6585fa)

    But Redux/Flux animation works thanks to CSS, since adding CSS class over and over would animate only at the moment it is newly added, and so perfect for UI. (So it is like a built-in one-offs) In Unity, calling play on `Animation` is not quite the same as it restarts.

    I found one more big problem by relying on ECS's changed, one other entity is able to trigger "changed" for all entities in a chunk! So imagine I have 4 life bars (4 entities in the same chunk) which its life length is modified by one system. When state change the life point for one of the bar then all 4 bars will get re-rendered. (We cannot determine which one changed) Rerendering to the same value is mostly fine, until it is involving some kind of one-off animation that break the rule of DoD.

    My current idea is to relax one constraint that a view can not only handle state data changes, but also know which action that cause the data change. Then I am able to trigger the correct one-off animations based on the action, while update the content based on data.