Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Best way to make an input buffer?

Discussion in 'Editor & General Support' started by ThiroSmash, Mar 13, 2020.

  1. ThiroSmash

    ThiroSmash

    Joined:
    Aug 11, 2019
    Posts:
    7
    I want to create an input buffer similar to that of a fighting game - the inputs from the player are stored for a small amount of time if at the time the buttons are pressed the action can't be performed yet.

    I've found two possible methods of "counting time": either counting the frames that pass via Time.frameCount (and each frame would be roughly 1/60th of a second), or counting the actual time via Time.time.

    However, I don't know how each of these would work if there are slight performance issues. I imagine that, if counting by frames, the actual buffer window could vary; and if counting by seconds, the amount of frames of the buffer would vary. Which one would be more advisable?

    Another thing - is how to actually make the logistics. I think simply storing the time (or frame) of when the input was pressed, then comparing it to the current time is the most efficient way, like so:
    Code (CSharp):
    1. if(time.Time - timeOfPress < bufferTimeWindow)
    2.     //input is still within buffer window
    But again, I might be wrong on this one. If there are better ways to do this, I'd like to know.
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I'd count by time, because frame rates will vary during gameplay. I would just create a class to represent an input, then when checking for inputs you create an instance of the class with a timestamp and throw it into a list. After checking inputs if an action is allowed you loop through the list and check for timestamps before taking each action. Just off the top of my head.


    Edit: Here's just a pretty simple example. Note it probably is full of syntax errors because I just wrote it directly into the forum without checking anything. But this is just to give you an idea of how you could implement something like this.
    Code (csharp):
    1. private List<ActionItem> inputBuffer = new List<ActionItem>();  //The input buffer
    2. private bool actionAllowed;  //set to true whenever we want to process actions from the input buffer, set to false when an action has to wait in the buffer
    3. //Notice I don't have any code here which sets actionAllowed to true, because that probably depends on states like in the middle of throwing a punch animation, or checking if a jump has finished, or whatever
    4.  
    5. void Update()
    6. {
    7.     checkInput();
    8.     if (actionAllowed)
    9.     {
    10.         tryBufferedAction();
    11.     }
    12. }
    13.  
    14. //Check inputs here, and add them to the input buffer
    15. private void checkInput()
    16. {
    17.     if (Input.GetKeyDown(Keycode.W))
    18.     {
    19.         inputBuffer.Add(new ActionItem(ActionItem.InputAction.Jump, Time.time));
    20.     }
    21.     //Add checks for all other inputs here
    22. }
    23.  
    24. //Call when we want to process the inputBuffer
    25. private void tryBufferedAction()
    26. {
    27.     if (inputBuffer.count > 0)
    28.     {
    29.         foreach (ActionItem ai in inputBuffer.ToArray())  //Using ToArray so we iterate a copy of the list rather than the actual list, since we will be modifying the list in the loop
    30.         {
    31.             inputBuffer.Remove(ai);  //Remove it from the buffer
    32.             if (ai.CheckIfValid())
    33.             {
    34.                 //Means the action is still within the allowed time, so we do the action and then break from processing more of the buffer
    35.                 doAction(ai);
    36.                 break;  //We probably only want to do 1 action at a time, so we just break here and don't process the rest of the inputBuffer
    37.             }
    38.         }
    39.     }
    40. }
    41.  
    42. private void doAction(ActionItem ai)
    43. {
    44.     //code to jump, punch, kick, etc
    45.  
    46.  
    47.     actionAllowed = false;  //Every action probably has some kind of wait period until the next action is allowed, so we set this to false here.
    48.     //Some code somewhere else needs to be written to set it back to true
    49. }
    50.  
    51.  
    52.  
    Code (csharp):
    1. public class ActionItem{
    2.  
    3.     public enum InputAction {Punch, Kick, Jump, Block};
    4.     public InputAction Action;
    5.     public float Timestamp;
    6.  
    7.     public static float TimeBeforeActionsExpire = 2f;
    8.  
    9.     //Constructor
    10.     public ActionItem(InputAction ia, float stamp)
    11.     {
    12.         Action = ia;
    13.         Timestamp = stamp;
    14.     }
    15.  
    16.     //returns true if this action hasn't expired due to the timestamp
    17.     public bool CheckIfValid()
    18.     {
    19.         bool returnValue = false;
    20.         if (Timestamp + TimeBeforeActionsExpire >= Time.time)
    21.         {
    22.             returnValue = true;
    23.         }
    24.         return returnValue;
    25.     }
    26. }
     
    Last edited: Mar 13, 2020