Search Unity

Problem Writing to CommandBuffer in Extension Method

Discussion in 'Entity Component System' started by RandyBuchholz, Jun 30, 2019.

  1. RandyBuchholz

    RandyBuchholz

    Joined:
    Sep 23, 2016
    Posts:
    51
    I'm unable to write to the default CommandBuffer PostUpdateCommands in a ComponentSystem inside an extension method.

    I'm wrapping this type of action (adding a State), in an extension method - SetState().

    Code (CSharp):
    1. PostUpdateCommands.SetSharedComponent(salesOrder, new SalesOrderState { State = SalesOrderStates.WorkOrder });
    // Extension Method
    Code (CSharp):
    1. public static class EntityCommandBufferExtensions {
    2.     public static void SetState<TSharedComponent, TState>(this EntityCommandBuffer buffer, Entity entity, TState state)
    3.          where TSharedComponent : struct, ISharedComponentData where TState : Enum {
    4.        
    5.         var stateObject = Activator.CreateInstance<TSharedComponent>();
    6.         var stateField = typeof(TSharedComponent).GetField("State");
    7.         stateField.SetValue(stateObject, state);
    8.         buffer.SetSharedComponent(entity, stateObject);
    9.     }
    10. }
    I use it like this:

    Code (CSharp):
    1. PostUpdateCommands.SetState<SalesOrderState, SalesOrderStates>(salesOrder, SalesOrderStates.WorkOrder);
    The code runs, but fails silently - the new state isn't being updated.
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Not an answer to your question, but you don't need to use reflection/activator to create and set your instance. (Does reflection work in burst? Could be your issue)

    Code (csharp):
    1. var stateObject = default(TSharedComponent); // or new TSharedComponent()
    2. startObject.State = state;
     
  3. RandyBuchholz

    RandyBuchholz

    Joined:
    Sep 23, 2016
    Posts:
    51
    Thanks for the "default(T)". Using "new" won't work because inside the generic class you can't use "new" unless T has the new() generic constraint. You can't put "where new ()" on a struct, only a class.
     
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Yes in a generic you need either the new() OR struct constraint to create a new instance as structs always have an empty constructor (hence new() makes no sense as it's implicit).

    So new TSharedComponent() works fine. I even tested it before I posted originally just to confirm my knowledge (though my ide recommends changing to default).
     
  5. RandyBuchholz

    RandyBuchholz

    Joined:
    Sep 23, 2016
    Posts:
    51
    You're right. I dumb-guy-typo tried to "new" my enum "new TState()". lol