Search Unity

Feedback Add constructors to components

Discussion in 'Entity Component System' started by Deleted User, Aug 14, 2019.

  1. Deleted User

    Deleted User

    Guest

    This is a small feedback on default ECS components.
    I have noticed that official ECS components don't have constructors. This increases boilerplate code. Since you need to use object initialization pattern and that requires you to write the name of every property.
    Take this line as an example:
    Translation position = new Translation { Value = new float3(0, 0, 0) };

    if Translation had constructor, it could be like this:
    Translation position = new Translation(new float3(0, 0, 0));

    Since Translation only has one field, it could have another constructor like this:
    Translation position = new Translation(0, 0, 0);


    As you can see having constructors reduces the clutter and size of the code.
     
    herkip and JesOb like this.
  2. SugoiDev

    SugoiDev

    Joined:
    Mar 27, 2013
    Posts:
    395
    Constructors sometimes can have hidden costs.
    They can also change with time and you could end up paying those costs in the future without knowing.
    I got a nice perf improvement on a Unity project just by not using Vector# constructors in hot paths.

    With performance-oriented stuff it is sometimes better to be very explicit to get most performance and predictability.
     
  3. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    If such constructors had a major performance cost, that's a bug. The output code should be equivalent in Burst.
     
    herkip, Deleted User and JesOb like this.
  4. Deleted User

    Deleted User

    Guest

    Agreed.

    Also, having constructors enable you to have immutable structs. If it doesn't improve performance, it shouldn't have a cost.
     
  5. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    67
    Burst can easily inline and optimize constructors. Even complex structure like this:

    Code (csharp):
    1.  
    2. struct SimpleConstruct{
    3.     public int x;
    4.     public int y;
    5.  
    6.     public SimpleConstruct(int _x)
    7.     {
    8.         x = _x;
    9.         IndirectAssignment(out y);
    10.     }
    11.  
    12.     static void IndirectAssignment(int i, out int v)
    13.     {
    14.         v = 10*i;
    15.     }
    16. };
    17.  
    can be reduced to few instructions (for constant _x it's one 64-bit MOV). Il2cpp can probably optimize it through c++ compiler. JIT compiler (mono) struggle with constructor optimizations and usually generate a call to the constructor method. This can cause performance impact, especially in loops. There is another reason why you should not use constructors in ECS. Constructors are ECS anti-pattern. They are methods, and methods are implicitly modifying the state of a component. You can not tell anything about its values after executing constructor. In ECS pattern, the system is responsible for the explicit component set/update.
     
    Last edited: Aug 16, 2019
    SugoiDev likes this.
  6. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    I would argue against such a broad generic statement. There's a difference between utility and abstraction. Utility is reducing boilerplate (original topic) or reducing code duplication (when the component needs to get constructed from a different representation in multiple places in the code). Besides, constructors still force the system to set and update the component in Unity's ECS because components are structs (pass by value). If you can't tell how a constructor is going to initialize a component for a given set of inputs, that means someone forgot to type /// above the constructor.
     
    Rennan24 and JPrzemieniecki like this.