- Home /
Problem is solved
Instantiate gets called every frame and doesn't wait for timer
Hey, I want to Instantiate a bullet every 2 seconds or so but it gets called every frame even though I set an interval. What's wrong with my code?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tower : MonoBehaviour
{
GameObject[] enemyList;
float attackRange = 5f;
GameObject nearestEnemy;
GameObject bulletPrefab;
float attackInterval = 2f;
float nextAttack = 0f;
void Start()
{
bulletPrefab = Resources.Load<GameObject>("Prefabs/BulletPrefab");
}
void Update()
{
findNearestEnemy();
if (nextAttack <= 0)
{
nextAttack = attackInterval;
if (nearestEnemy != null)
{
if (Vector2.Distance(nearestEnemy.transform.position, transform.position) <= attackRange)
{
Instantiate(bulletPrefab, transform.position, Quaternion.identity);
nearestEnemy = null;
}
}
}
else
{
nextAttack -= Time.deltaTime;
}
}
void findNearestEnemy()
{
enemyList = GameObject.FindGameObjectsWithTag("Enemy");
if (enemyList.Length != 0)
{
float minDist = Mathf.Infinity;
foreach (var enemy in enemyList)
{
float dist = Vector2.Distance(transform.position, enemy.transform.position);
if (dist < minDist)
{
nearestEnemy = enemy;
}
}
}
}
}
Answer by ShadyProductions · Mar 20, 2020 at 08:15 PM
1). You never actually set or reset your nextAttack it is always <= 0
, after instantiate reset it to 2f
2). You have a lot of inefficiency in your method. (calling FindGameObjectsWithTag every frame)
You should consider caching your enemies.
With caching he mean that you could create a List or an Array, in which you save references to your Enemies each time when you create them. In this way it is easier just to get access to all of them, e.g in a foreach or for loop ins$$anonymous$$d of searching in the whole scene in each frame first, what's usually not very performant.
nextAttack gets reset every time on line 24
nextAttack = attackInterval;
I just noticed, well then it should work fine. $$anonymous$$aybe you should add a debug line, and it shouldn't be called every frame.
With caching I mean putting this line enemyList = GameObject.FindGameObjectsWithTag("Enemy");
in Start() only.
Yes, if no new enemies are spawned after the scene has started, during the game, then this is also an alternative :-)
To point 1.) Line 24 actually resets the nextAttack. You just should initialize it in your Start() method also. To point 2.) I agree
And then you should maybe check in line 22 for 0f ins$$anonymous$$d of 0, because it is a float and that causes sometimes problems. The algortithm itself seems to be ok in my oppinion.
Still doesn't work. I really don't get it...
Could you maybe show your latest script again?
I just saw that the bullet prefab had the tower script on it.. Took me like 2h to solve this problem.. Thank you guys anyways :)
Oh ok, that explains it of course :-D
Then you have called it each time on Start() and Spawned the next bullet immediatelly.
Thanks for your update, good to know, that at least the Script works.
Follow this Question
Related Questions
Timer Progress Bar 2 Answers
how to Subtract string from TimeSpan 0 Answers
UnityOSC and timer 0 Answers
Resetting Timer Using PlayerPrefs? (JS) 1 Answer
Timer with Coroutine 3 Answers