Search Unity

[SOLVED] Replace "continuous" tag with Player Input Component

Discussion in 'Input System' started by AlphaDreams, Aug 9, 2019.

  1. AlphaDreams

    AlphaDreams

    Joined:
    Jan 21, 2015
    Posts:
    30
    Since the version 0.9.x, the tag "continuous" is dropped for the new input system. If we want to get the values for a particular input action, we can use
    ReadValue<T>()
    .

    But in my project (a 2-player local game), I use the events send (by Broadcasting) by the built-in Player Input Component, instantiated by the Player Input Manager Component.

    Since my actions can't be "continuous", my events now aren't send every frame, and my game is quite broken.

    Is there a possibility to bypass this, and force the Player Input Component to send events even if there is no input ? Or is it possible to use
    ReadValue<T>()
    with the instance of Player Input ?
     
  2. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    It's possible to use
    ReadValue<T>
    with player input. I track value changes on my own:


    Code (CSharp):
    1. [UpdateInGroup(typeof(TiInputSystemGroup))]
    2.     public class PlayerInputAdapterSystem : ComponentSystem
    3.     {
    4.         private readonly EntityQueryBuilder.F_CDD<PlayerInputAdapter, InputFrameRawData, PlayerIndex>
    5.             m_processPlayer;
    6.  
    7.         private EntityQuery m_query;
    8.  
    9.         public PlayerInputAdapterSystem() => m_processPlayer = ProcessPlayer;
    10.  
    11.         protected override void OnCreate()
    12.         {
    13.             m_query = GetEntityQuery(
    14.                 ComponentType.ReadOnly<PlayerInputAdapter>(),
    15.                 ComponentType.ReadWrite<InputFrameRawData>(),
    16.                 ComponentType.ReadWrite<PlayerIndex>());
    17.  
    18.             RequireForUpdate(m_query);
    19.         }
    20.  
    21.         protected override void OnUpdate()
    22.         {
    23.             Entities.With(m_query).ForEach(m_processPlayer);
    24.         }
    25.  
    26.         private static void ProcessPlayer(
    27.             PlayerInputAdapter adapter,
    28.             ref InputFrameRawData rawData,
    29.             ref PlayerIndex playerIndex)
    30.         {
    31.             PlayerInput playerInput = adapter.PlayerInput;
    32.             playerIndex = new PlayerIndex {Value = playerInput.playerIndex};
    33.  
    34.             InputActionMap gameplay = adapter.NormalGameplay;
    35.  
    36.             if (!gameplay.enabled)
    37.                 return;
    38.  
    39.             ReadOnlyArray<InputAction> actions = gameplay.actions;
    40.  
    41.             rawData.Data.c0.xy = actions[0].ReadValue<Vector2>(); //dpad
    42.             rawData.Data.c0.zw = actions[1].ReadValue<Vector2>(); //stick
    43.             rawData.Data.c1.x = actions[2].ReadValue<float>(); //jump
    44.             rawData.Data.c1.y = actions[3].ReadValue<float>(); //attack regular
    45.             rawData.Data.c1.z = actions[4].ReadValue<float>(); //attack bold
    46.             rawData.Data.c1.w = actions[5].ReadValue<float>(); //attack grab
    47.             rawData.Data.c2.x = actions[6].ReadValue<float>(); //evade left
    48.             rawData.Data.c2.y = actions[7].ReadValue<float>(); //evade right
    49.             rawData.Data.c2.z = actions[8].ReadValue<float>(); //start
    50.             rawData.Data.c2.w = actions[9].ReadValue<float>(); //select
    51.         }
    52.     }
    Then I do processing in a job system, here's the critical function:

    Code (CSharp):
    1. public static void Process(
    2.                 DynamicBuffer<InputFrameHistory> frames,
    3.                 /*[ReadOnly] ref*/
    4.                 in InputFrameRawData rawData,
    5.                 ref InputFrameStatus status,
    6.                 double2 deadZones)
    7.             {
    8.                 float4 axes = rawData.Data.c0;
    9.                
    10.                 InputFrameFlags dpadValue = ResolveDirections(axes.xy);
    11.                 InputFrameFlags stickValue = ResolveStick(axes.zw, deadZones);
    12.                 var directions = (InputFrameFlags) select((int) stickValue, (int) dpadValue, dpadValue != 0);
    13.  
    14.                 bool4x2 buttonsValue = new float4x2(rawData.Data.c1, rawData.Data.c2) > new float4x2();
    15.                 var buttons = (InputFrameFlags) ((bitmask(buttonsValue.c0) << 4) | (bitmask(buttonsValue.c1) << 8));
    16.  
    17.                 InputFrameFlags previous = status.Current;
    18.  
    19.                 status.Current = directions | buttons;
    20.                 InputFrameFlags changed = status.Current ^ previous;
    21.                 status.Holds = UpdateHolds(status.Holds, status.Current, changed);
    22.                
    23.                 if (changed == InputFrameFlags.None)
    24.                     return;
    25.  
    26.                 InputFrameFlags pressed = ~previous & changed & status.Current;
    27.                 InputFrameFlags released = previous & changed & ~status.Current;
    28.  
    29.                 frames.Insert(0, new InputFrameHistory(status.Current, changed, pressed, released));
    30.             }
     
    AlphaDreams likes this.
  3. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    669
    Do note, for the buttons actions, I have found it best to change them to Value actions, with the Digital Type. This works best for my use-case (discrete inputs for beat-em-up/platformer with a combo system), yours may vary.
     
  4. AlphaDreams

    AlphaDreams

    Joined:
    Jan 21, 2015
    Posts:
    30
    It seems that the solution that I tried is quite the same as yours (I just use the generated c# class to get my
    InputAction
    s by ID, but it's basically the same code as yours).

    So thank you @recursive , it reassures me !

    If it can help someone else, here is how I did it (in a very straightforward way) :

    Code (CSharp):
    1. // I want to get the PlayerInput component for Player 1
    2. playerInput = PlayerInput.GetPlayerByIndex(0);
    3.  
    4. // Then, I create an instance of the C# class generated by the InputSystem
    5. SpiritArenaInputs saInputs = new SpiritArenaInputs();
    6.  
    7. // Trying to get one InputAction is quite easy
    8. InputAction shootAction = playerInput.actions.TryGetAction(saInputs.Game.Shoot.id);
    9.  
    10. // And then, when I need it, I use ReadValue
    11. Vector2 aim = shootAction.ReadValue<Vector2>();
     
    Augustolego55 and recursive like this.