Search Unity

  1. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Methods and Properties on Components

Discussion in 'Data Oriented Technology Stack' started by TommiH, May 24, 2018.

  1. TommiH

    TommiH

    Joined:
    Jan 14, 2008
    Posts:
    252
    Hello,

    From the simple examples in the various videos I understood that components are supposed to simply contain data, as opposed to the old Components that also contain their own functionality. But in the TwoStickShooter project, there's a component (PlayerInput) with a property (Fire), which uses a field in the component (FireCooldown), as well as a library function call (math.length) to calculate its value.

    Is there some guidelines for how much you should use properties and methods in components? The logic in PlayerInput.Fire could easily have been placed in PlayerInputSystem instead. Is this just a matter of code design?
     
    starikcetin and PhilSA like this.
  2. jooleanlogic

    jooleanlogic

    Joined:
    Mar 1, 2018
    Posts:
    364
    I think this is just design. One of the design problems I've encountered in ecs is how you maintain consistent state in a Component. The two approaches I've found so far are to either add code to a Component via getters/setters, or to use ordered Systems.
    Both have pros and cons.

    By consistent state, I mean where you have properties that have dependencies on each other. E.g. You have an EngineComponent that has power and maxPower and power needs to be clamped between 0 and maxPower. You can put that code in component setters and guarantee power will always be within a valid range.

    In the systems approach with data only components, you would have the systems that set power and maxPower, then a system that clamps power to maxPower, and then systems that readonly on power. With this approach, the systems must be strictly ordered to maintain consistent state.

    In OO parlance, the first approach is simpler but more tightly coupled. The second approach is loosely coupled and more flexible, but can require complex ordering and is thus harder to jobify.
    You can always use combinations of the two as well.
     
  3. TommiH

    TommiH

    Joined:
    Jan 14, 2008
    Posts:
    252
    Thanks for your response!

    So I suppose a reasonable rule of thumb would be: put logic into system unless you really feel it should be in the component.

    However: Is there something keeping me from calling some completely different class from the logic in my component (like calling a method on an object / struct referenced in the component, or calling a static method)? I'm assuming the job system would somehow prevent that as you have to explicitly declare data, but I'm a bit unclear on where the borders of the job's data / logic space are drawn.
     
  4. jooleanlogic

    jooleanlogic

    Joined:
    Mar 1, 2018
    Posts:
    364
    I haven't tried that so I'm not sure what the compiler or job system would do.
    Outside of the job system though, I'm no sure there's any restrictions on doing whatever you wanted to in struct methods.
    I can't see it being a good idea to put too much other code on them except for that which maintains the internal state though.

    That two stick shooter example uses the Fire method as a conditional statement but you could achieve the same by adding a FireComponent (like an event) to the ship, then having a System which performs the fire behaviour.

    This goes back to that two ways of doing things. You can have components that permanently exist on an Entity, and systems that use conditional checks on its properties every frame to determine whether to carry out an operation. Or you can add Components like events only when they're needed.
    It's like a state machine approach vs an event approach.
    Whether one's more performant that then other probably depends on the frequency of the event. Adding a component moves an Entity from one chunk to another so there's a cost there.

    Coming from OO, it's a significant paradigm shift going back to a procedural way of doing things. For now, I'm going with a 'code in systems' only and 'component event' approach to see what challenges that throws up. I won't know whether that's a good/bad idea until I get down the track a bit.
     
  5. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,496
    - Calling method on an object : This is not possible as you are not allowed to have an object in IComponentData. It will says IComponentData does not allow managed objects inside it.
    - Static method : I think this is possible if it just contain some logic (could be inlined?), but if it in turn uses static variables it is only possible right now and will be broken in the future release. The doc says there will be a check in the future so that a static variable access is not possible from inside the job. (https://github.com/Unity-Technologi...system.md#job-system-tips-and-troubleshooting) If you don't use IComponentData in jobs statics are fine.
     
  6. TommiH

    TommiH

    Joined:
    Jan 14, 2008
    Posts:
    252
    Thanks to the both of you for your responses! You've clarified this to me.
     
unityunity