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. Dismiss Notice

How to execute different actions on the same button (code included)

Discussion in 'Scripting' started by Piotrone, Oct 9, 2020.

  1. Piotrone

    Piotrone

    Joined:
    Mar 6, 2015
    Posts:
    36
    Hi all, I have one button (or tap on screen) that executes a different action (e.g. shoot, pull lever, eat) depending on a necessary condition (has gun, has lever, has cake) otherwise executes a default action (jump).
    Two actions shouldn't happen at the same time and I want a delay between the actions

    This is the file that translates the button/tap into either an action or a jump, and adds a delay. And isn't working
    Code (CSharp):
    1. public class PlayerActionManager : MonoBehaviour
    2. {
    3.     private bool _isJumping;
    4.     public bool IsJumpig { get => _isJumping;  }
    5.     private PlayerInput _playerInput;
    6.     private List<IActionable> _actionables = new List<IActionable>();
    7.     private float _timer;
    8.  
    9.     private void Start()
    10.     {
    11.         var actionable = FindObjectsOfType<MonoBehaviour>().OfType<IActionable>();
    12.         foreach (IActionable a in actionable)
    13.         {
    14.             _actionables.Add(a);
    15.         }
    16.         _playerInput = GetComponent<PlayerInput>();
    17.     }
    18.  
    19.  
    20.     private void Update()
    21.     {
    22.         foreach (IActionable actionable in _actionables)
    23.         {
    24.             if (actionable.CanExecuteAction)
    25.             {
    26.                 if (_playerInput.ActionInput)
    27.                 {
    28.                     actionable.ExecuteAction();
    29.                     _timer = 1f;
    30.                 }
    31.             }  
    32.             else
    33.             {
    34.                 if (_timer < 1f)
    35.                 {
    36.                     _timer += Time.deltaTime;
    37.                 }
    38.                 else
    39.                 {
    40.                     _isJumping = _playerInput.ActionInput;
    41.                     _timer = 0;
    42.                 }
    43.             }
    44.         }
    45.      }
    46. }
    Here's the rest of the setup (simplified code)

    Code (CSharp):
    1. public class PlayerInput : MonoBehaviour
    2. {
    3. public bool ActionInput
    4.     {
    5.         get
    6.         {
    7.             if (_touchInput != null)
    8.             {
    9.                 if (_touchInput.screenTouched)
    10.                 {
    11.                     return true;
    12.                 }
    13.             }
    14.             return Input.GetKey(KeyCode.UpArrow);
    15.         }
    16.     }
    17. }

    Code (CSharp):
    1. public class CharachterMovement : MonoBehaviour
    2. {
    3.  void Update()
    4.     {
    5.         Move(_playerActionManager.IsJumping);
    6.     }
    7. }
    8.   public void Move(bool canJump)
    9.   {
    10.  
    11.    if (IsGrounded && canJump)
    12.         {
    13.               IsGrounded = false;
    14.             _rigidbody2D.AddForce(new Vector2(0f, _jumpForce));
    15.         }
    16.       }
    17. }
    Code (CSharp):
    1. public interface IActionable
    2. {
    3.     bool CanExecuteAction { get; }
    4.     void ExecuteAction();
    5. }
    Code (CSharp):
    1. public class PickUpManager : MonoBehaviour, IActionable
    2. {
    3.     private bool _isLoaded;
    4.     public bool CanExecuteAction { get => _isLoaded; }
    5.  
    6.     private void OnTriggerEnter2D(Collider2D collision)
    7.     {
    8.         _isLoaded = true;
    9.         }
    10.     }
    11.  
    12.     private void Update()
    13.     {
    14.         if (_canThrow)
    15.         {
    16.             _throwable.Throw();
    17.                 _isLoaded = false;
    18.                 _canThrow = false;
    19.             }
    20.         }
    21.     }
    22.  
    23.     public void ExecuteAction()
    24.     {
    25.         _canThrow = true;
    26.     }
    27. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,750
    Break things apart a bit.

    - Capture the intent to tap a button into a variable.

    - Operate your cooldown timer(s)

    - If the timers are proper to allow input, then:

    ---- decide what to do (select only ONE action if that's what you want)

    ---- do it

    ---- set any timer values you need
     
  3. Piotrone

    Piotrone

    Joined:
    Mar 6, 2015
    Posts:
    36
    Thank you for your answer.
    Yes, that I have in _playerInput.ActionInput

    But If I operate the cooldown first, I'd have a delay executing in the first action, wouldn't I? I want the first action to trigger right away, and then have a delay before the next action.
     
  4. Piotrone

    Piotrone

    Joined:
    Mar 6, 2015
    Posts:
    36
    One issue I found is that all the actions (jump, shoot, pull lever, eat) happen in the update and that the player input is read in update too. So if the button is not being pressed anymore (false) this interrupts the action, but instead I want the action to continue.

    My code above attempts to model this:

    if a button is pressed
    if the player can jump (e.g. none of the other action conditions are true)
    then the player jumps​
    if the player can't jump (e.g. any of the other action condition is true)
    then the action starts playing until the end
    the button can be pressed again only after x seconds​
     
    Last edited: Oct 10, 2020