0

A few days ago I first used the new input system of unity for my game and I ran into a problem. So basically I cant seem to figure out how to implement cooldown in the new system. Either it just overall doesnt work, it breaks other code or it just gives me a hundred errors. I just cant figure it out. I hope someone can help me implement just a very simple adjustable cooldown timer for the playerattack. I already want to thank everyone helping me with this!

Btw: I used the startTimeBtwAttack and timeBtwAttack variables for my cooldown in the past, but they dont work anymore. Had to remove some code so yeah...

PlayerAttack and Movement script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Move : MonoBehaviour {

public int damage; private float timeBtwAttack; public float startTimeBtwAttack;

public float attackRangeX; public float attackRangeY;

public Transform attackPos; public LayerMask whatIsEnemies;

//Move Start [SerializeField] private Rigidbody2D rb2D; [SerializeField] private float speed; private Vector2 moveInputValue;

private void OnMove(InputValue value) { moveInputValue = value.Get<Vector2>(); Debug.Log(moveInputValue); } private void MoveLogicMethod() { Vector2 result = moveInputValue * speed * Time.fixedDeltaTime; rb2D.velocity = result; } private void FixedUpdate() { MoveLogicMethod(); } //Move End

//Attack Start

private void OnPlayerAttacking() { Collider2D[] enemiesToDamage = Physics2D.OverlapBoxAll(attackPos.position, new Vector2(attackRangeX, attackRangeY), 0, whatIsEnemies); for (int i = 0; i < enemiesToDamage.Length; i++) { enemiesToDamage[i].GetComponent<Enemy>().TakeDamage(damage); } timeBtwAttack = startTimeBtwAttack; } void OnDrawGizmosSelected(){

    Gizmos.color = Color.black;
    Gizmos.DrawWireCube(attackPos.position, new Vector3(attackRangeX, attackRangeY, 1));

} //Attack End }

Then there is the enemyScript for the enemy to receive damage:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Enemy : MonoBehaviour {

public int health; private Animator anim;

void Update(){
if(health <= 0){

    Destroy(gameObject);
}

}

public void TakeDamage(int damage){ health -= damage; Debug.Log("damage TAKEN !");

} }

Let me know if you need more infos!

Hammynator
  • 33
  • 9
  • 2
    "breaks other code or it just gives me a hundred errors." If you want help with this, show us what code it breaks, or what specific errors you get. – DMGregory Jan 13 '23 at 21:21
  • It doesnt specifically break the code, its just not working and sometimes affects code, but its not a big problem. I personally think its not very important to say in which way my code doesnt work, since it doesnt work. Just ignore this line: Either it just overall doesnt work, it breaks other code or it just gives me a hundred errors – Hammynator Jan 13 '23 at 21:25

2 Answers2

1

You can solve this the same way I explained previously. Keep a timestamp of your last successful attack, and compare it to the time when the trigger condition fires (in this case, when the button press causes OnPlayerAttacking() to be called). If less time has passed than your desired cooldown, abort execution without performing the attack.

[Tooltip("Minimum time between attack inputs, in seconds")]
public float attackCooldown = 0.5f;

float _lastAttackTime;

private void OnPlayerAttacking() { // If attacking too close to previous attack, ignore this input. if (Time.time - _lastAttackTime < attackCooldown) return;

var enemiesToDamage = Physics2D.OverlapBoxAll(
           attackPos.position,
           new Vector2(attackRangeX, attackRangeY),
           0,
           whatIsEnemies
);

foreach (var enemy in enemiesToDamage) {
     enemy.GetComponent&lt;Enemy&gt;().TakeDamage(damage);
}

_lastAttackTime = Time.time;

}

As I mentioned before, comparing float timestamps is not good when you need millisecond precision, but for accepting/rejecting inputs, frame precision on the order of 10 ms is plenty, and floats are good enough for that, even when your game has been running for days.

DMGregory
  • 134,153
  • 22
  • 242
  • 357
1

Here is another approach, using a cooldown timer that gets decremented and reset in the update method.

For this to work, you must set isPressedButton whenever your player attack button is pressed and released.

// Input state
private bool isPressedButton;

// Button cooldown [Tooltip("Minimum time between button inputs being processed (in seconds)")] [SerializeField] private float buttonCooldownDuration = 0.4f; private float buttonCooldownCurrent;

// Update method void Update() { // If pressed the button, and the cooldown is over if (isPressedButon && buttonCooldownCurrent <= 0) { // Perform the button action...

    // Reset the button cooldown
    buttonCooldownCurrent = buttonCooldownDuration;

    // Skip the rest
    return;
}

 // Decrement the button cooldown
 buttonCooldownCurrent -= Time.deltaTime;

} ```

Ben
  • 487
  • 2
  • 4
  • 14