1

Iteration of every variable in the foreach is not assigned to the weapon iterated.

public class CharacterAttack : MonoBehaviour { #region Fields private Weapon weapon; public List<WeaponData> weapons; #endregion private void Awake() { weapon = FindObjectOfType<Weapon>(); StartCoroutine(Shoot()); } private IEnumerator Shoot() { while (true) { foreach (var data in weapons) { var waitingShoot = data.cooldown; yield return new WaitForSeconds(waitingShoot); weapon.Shoot(); } } } } 

I'm doing a clone of Vampire Survivor where the character has a series of weapons that can shoot with their own variable (cooldown,range ecc.). As you can see from the code I have a list of weapons, and every weapon has its cool-down. Unfortunately, with the code I wrote, every weapon is shooting with the same cool-down timing. What I want is for each weapon to shoot with its own cool-down instead.

The script Shoot has only the instatiate().

2
  • 1
    One way is to create a priority queue and each time you fired a weapon you enqueue it with "time to fire" timestamp as priority. Then in your loop you pick the item with smallest priority (smallest "time to fire" timestamp) and wait that amount of time. This is a general idea to handle all kind of cooldowns in a single-threaded manner. Commented Jun 8, 2023 at 20:37
  • Why can't we have "List of nice-things-that-dont-hurt-people that use own variable" instead? Commented Jun 13, 2023 at 10:41

2 Answers 2

1

Just use coroutine for each weapon and use bool for stop them.

public class test : MonoBehaviour { #region Fields public List<WeaponData> weapons = new(); public bool canAttack = false; #endregion private void Awake() { StartShooting(); } private void StartShooting() { canAttack = true; foreach (var weapon in weapons) { StartCoroutine(Shoot(weapon)); } } private IEnumerator Shoot(WeaponData data) { while (canAttack) { var waitingShoot = data.cooldown; Debug.Log(waitingShoot); yield return new WaitForSeconds(waitingShoot); //...shoot } } } 
Sign up to request clarification or add additional context in comments.

Comments

0

Thank you who answer my question, I want to post how i resolved this.

The first class weapon has two methods. One method instatiate the object The second method store the time passed from the last time i shoot. Then I shoot and set the cooldown to 0 again (equals to Time.time).

using UnityEngine; [Serializable] public class Weapon { public WeaponData weaponData; private Character character; private float lastTimeActivated; //public CharacterStats characterStats; public bool TryActivate(Character character) { if (Time.time > lastTimeActivated + weaponData.cooldown ) { Activate(character); lastTimeActivated = Time.time; return true; } return false; } private void Activate(Character character) { //GameObject projectile = weaponData.prefabAtLevel[0]; Object.Instantiate(weaponData.projectile, character.transform.position, character.transform.rotation); } } 

In the second part, in another script i use a foreach to recall the shoot of my weapon for every object in the list. I hope this will help someone too! P.s. sorry for my English

public class CharacterAttackWithWeapon : CharacterAttack { #region Fields public List<Weapon> weapons; #endregion private void Update() { foreach (var weapon in weapons) { weapon?.TryActivate(character); } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.