- Home /
foreach code causes lag spike C#
sorry about making another question but everytime i fix somthing another thing breaks, in this script, foreach at line 40 is making a huge lag spike any ideas on a fix? btw im sorry about the messy code, i only started learning this less than a week ago by my self.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PistolRay : MonoBehaviour {
bool canFire = true;
public GameObject decal;
public float clipAmmo = 8;
public float storedAmmo = 80;
float missingShots = 0;
GameObject player;
GameObject characterControler;
bool reloading = false;
private List<EnemyAi> enemies = new List<EnemyAi>();
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
player = GameObject.Find("Player");
CharacterControler characterControler = player.GetComponent<CharacterControler>();
characterControler.ammoCount = clipAmmo;
characterControler.totalAmmo = storedAmmo;
var enemyObjects = GameObject.FindGameObjectsWithTag("Enemy");
foreach(GameObject enemyObj in enemyObjects){
EnemyAi enemyAi = enemyObj.GetComponent<EnemyAi>();
if(enemyAi != null){
enemies.Add(enemyAi);
}
}
RaycastHit hit;
Ray shooterRay = new Ray(transform.position, transform.forward);
if(Input.GetButton("Fire1") && canFire && clipAmmo > 0){
if(GameObject.Find ("EnemyAi") != null){
foreach(EnemyAi enemy in enemies){
EnemyAi enemyAi = enemy.GetComponent<EnemyAi>();
enemyAi.couldHearGun = true;
StartCoroutine (SoundCooldown(1));
}
}
}
if(Input.GetButton("Fire1") && canFire && clipAmmo > 0){
Debug.DrawRay (transform.position, transform.forward, Color.green);
if(Physics.Raycast(shooterRay, out hit, Mathf.Infinity)){
if(hit.collider.tag == "Enemy"){
hit.transform.GetComponent<EnemyCC>().health -= 15;
}
}
var hitRotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
Instantiate(decal, hit.point, hitRotation);
canFire = false;
clipAmmo -= 1;
missingShots += 1;
StartCoroutine(FireRate(1));
}
if(Input.GetButtonDown("Fire1") && canFire && clipAmmo == 0 && !reloading){
reloading = true;
StartCoroutine(ReloadTime(3));
}
if(Input.GetButtonDown("Reload") && storedAmmo != 8 && !reloading){
reloading = true;
StartCoroutine(ReloadTime(3));
}
}
public IEnumerator FireRate (float delay){
yield return new WaitForSeconds(delay);
canFire = true;
}
public IEnumerator SoundCooldown(float delay){
GameObject enemy = GameObject.Find("EnemyAI");
EnemyAi enemyAi = enemy.GetComponent<EnemyAi>();
yield return new WaitForSeconds(delay);
enemyAi.couldHearGun = false;
}
public IEnumerator ReloadTime (float delay){
yield return new WaitForSeconds(delay);
reloading = false;
if(storedAmmo >= 8){
storedAmmo -= missingShots;
clipAmmo += missingShots;
missingShots = 0;
}
}
}
Answer by Voridian · Jul 22, 2014 at 10:42 AM
Sorry to waste peoples time but i got it now, StartCoroutine(SoundCooldown(1)); was firing off for every enemy in the scene, all i had to do was move it out of the foreach section. i an such an idiot sometimes :P
It's good you found the cause of your lag, but still take a look at storing references and object pooling ins$$anonymous$$d of getting them each frame. Getting a reference to something you already have a reference of is unnecessary and could also lead to performance issues, especially on mobiles and when using GameObject.Find() with a lot of GameObjects.
Answer by T27M · Jul 22, 2014 at 10:02 AM
My money would be on your call(s) to GameObject.Find (). GameObject.Find() isn't the most efficient method, plus you are calling it multiple times since you have it in Update(); If you're going to use it do it in Start().
The player for example:
player = GameObject.Find("Player");
You don't need to do this every frame, but only once at start and the same goes for getting the CharacterController.
If you are creating enemies dynamically and need a reference to all the enemies in the game use some sort of object pooling and store a reference to a List of the enemies rather than trying to find them each frame.
when i move those lines then i just get errors for them not not containing a definition when i call them in the update void
@Voridian I think you misunderstood the answer a little there.
T27$$anonymous$$ means that you get the references to the objects you need to find on Start and store them for later reference.
For example:
void Start() {
player = GameObject.Find("Player");
}
and remove line 24 (the same code)
Also, I noticed you use
GameObject enemy = GameObject.Find("EnemyAI");
several times. Perhaps this would be a good candidate for the above mentioned object pool, where you could update when adding and remove enemies ins$$anonymous$$d of having to find them every Update.
I hope this clarifies what you need to do a bit
Did you declare them in the class? It should look something like
// ...other variables
GameObject player;
CharacterControler characterControler;
private List<EnemyAi> enemies = new List<EnemyAi>();
// Use this for initialization
void Start ()
{
player = GameObject.Find ("Player");
characterControler = player.GetComponent<CharacterControler> ();
}
// Update is called once per frame
void Update ()
{
characterControler.ammoCount = clipAmmo;
characterControler.totalAmmo = storedAmmo;
var enemyObjects = GameObject.FindGameObjectsWithTag ("Enemy");
foreach (GameObject enemyObj in enemyObjects) {
EnemyAi enemyAi = enemyObj.GetComponent<EnemyAi> ();
if (enemyAi != null) {
enemies.Add (enemyAi);
}
}
RaycastHit hit;
Ray shooterRay = new Ray (transform.position, transform.forward);
if (Input.GetButton ("Fire1") && canFire && clipAmmo > 0) {
// What is the "EnemyAI" GameObject?
// Try this ins$$anonymous$$d?
if (enemies.Count > 0) {
foreach (EnemyAi enemy in enemies) {
EnemyAi enemyAi = enemy.GetComponent<EnemyAi> ();
enemyAi.couldHearGun = true;
StartCoroutine (SoundCooldown (1));
}
}
}
}
oh ok, so does:
CharacterControler characterControler = player.GetComponent<CharacterControler>();
get moved as well? because that causes an error with:
characterControler.ammoCount = clipAmmo;
characterControler.totalAmmo = storedAmmo;
EDIT: also the lag spike is still there. only way to get rid of i have found so far is removing everything to do with foreach
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Question on Using a Foreach Loop on Nested Children 1 Answer
Distribute terrain in zones 3 Answers
Multiple Cars not working 1 Answer
How can i stop my game from laging during instantiation? C# 2 Answers