Search Unity

Bug InputEvent does not fire exactly once

Discussion in 'NetCode for ECS' started by Misterturtle, Sep 20, 2023.

  1. Misterturtle

    Misterturtle

    Joined:
    May 25, 2017
    Posts:
    20
    Documentation states: By using the InputEvent type within IInputComponentData inputs you can guarantee one off events (for example gathered by UnityEngine.Input.GetKeyDown) will be synchronized properly with the server and registered exactly once.

    This ignores the fact that the client must set the InputEvent to default on the following frame for this to be accurate.

    Depending on how you interpret the documentation, this is a feature request, but squabbling aside, I would expect the following behavior out of InputData:

    Frame 0: Client -> Set (Count 1)
    Frame 0: Server -> Count 0
    End of Frame 0 -> Client automatically sends the input event data and sets InputEvent count back to 0
    ... Network Delay...
    Frame 15: Server Receives the input data (Count 1)
    Frame 15: Count stays 1 the entire Frame
    End of frame 15: Server sets the count back to 0

    Here is a MWE or the issue and the resolution:
    Branch with issue: https://github.com/Misterturtle/Deb...onentdata-debug/Assets/Scripts/DebugSystem.cs
    Branch with resolution: https://github.com/Misterturtle/Deb...nentdata-solved/Assets/Scripts/DebugSystem.cs
     
    Ice_106 likes this.
  2. Misterturtle

    Misterturtle

    Joined:
    May 25, 2017
    Posts:
    20
    Also, the documentation on this page under the Example Code section is outdated and still uses
    [GenerateAuthoringComponent]
     
  3. Ice_106

    Ice_106

    Joined:
    Jun 17, 2019
    Posts:
    5
    The correct approach seems to be this:
    [GhostInputSystemGroup]
    playerInputComp.jump = default;
    if(jumpKeyDown)
    playerInputComp.jump.Set();

    [PredictedSimulationSystemGroup]
    var networkTime = SystemAPI.GetSingleton<NetworkTime>();
    if (networkTime.IsFirstTimeFullyPredictingTick)
    if(playerInputComp.jump.IsSet)
    //jump
     
  4. CMarastoni

    CMarastoni

    Unity Technologies

    Joined:
    Mar 18, 2020
    Posts:
    894
    The documentation is unfortunately incorrect. The current requirement is that the events must be reset every tick.
     
  5. OuterGazer

    OuterGazer

    Joined:
    Jan 13, 2021
    Posts:
    11
    Is IsSet supposed to become false at the end of the server tick? Because I'm having currently a situation where I'm calling Set() on an InputEvent on the client and IsSet turns itself false before the next frame and turns true again in the subsequent frame without me doing anything even before the server runs its tick.

    It is quite annoying because I have the same button for crouching and then lying down and one press makes the character controller lay down because the system on the client runs several times before the server tick.
     
    Last edited: Mar 8, 2024
  6. SamuelBellomoUnity

    SamuelBellomoUnity

    Unity Technologies

    Joined:
    Sep 24, 2020
    Posts:
    14
    Like we mentioned above, the pattern is to reset your InputEvent each time before setting it conditionally. Are you saying you're trying this and it doesn't work?

    Code (CSharp):
    1. MyInput = default;
    2. if (Input.KeyDown ...)
    3.     MyInput.MyEvent.Set();
     
    Last edited: Mar 8, 2024
  7. NikiWalker

    NikiWalker

    Unity Technologies

    Joined:
    May 18, 2021
    Posts:
    315
    Note: Continuous character controller movements (like jumping) should not be guarded by IsFirstTimeFullyPredictingTick. IsFirstTimeFullyPredictingTick is to guard gameplay that cannot be rewound (events like entity creation, V/SFX etc).