- Home /
Lag when updating large amounts of objects
Hello! Working on an atmospherics simulator for a tile-based game. If a tile has a "leak" (either missing a diagonal/adjacent wall or floor tile), it drains the "oxygen level" of that tile (a float). I'm updating these values every five seconds based on the average of the values of all adjacent tiles. Unfortunately, I'm getting a lag spike every time it updates these values. Currently, I'm only trying to update a 9x9 grid of tiles (81 total) with one "leak" at one corner. The goal I'm trying to achieve works beautifully, it's just lag that's the issue at this point.
Two-part question for you all..
Is there any general procedure/guidelines to follow when updating large amounts of objects.
Is there anything specifically you could recommend for this script that would alleviate the lag issues?
Thanks in advance!
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class AtmosPropagation : MonoBehaviour {
Collider[] adjacentObjects;
List<GameObject> adjacentTiles;
List<GameObject> adjacentWalls;
public float oxygen;
float averageOxygen = 0f;
bool leak = false;
// Use this for initialization
void Start () {
adjacentTiles = new List<GameObject>();
adjacentWalls = new List<GameObject>();
adjacentObjects = Physics.OverlapSphere(transform.position, 1.5f);
if(adjacentObjects.Length == 0)
Debug.Log ("NO COLLISION!");
foreach(Collider col in adjacentObjects){
if(col.gameObject.tag == "Floor"){
adjacentTiles.Add(col.gameObject);
} else if(col.gameObject.tag == "Wall"){
adjacentWalls.Add(col.gameObject);
}
}
oxygen = 20f;
// [START ATMOS SIMULATION]
InvokeRepeating("PropagateAtmos", 5.0f, 5.0f);
}
// Update is called once per frame
void Update () {
}
public void PropagateAtmos(){
CheckForLeaks();
foreach(GameObject go in adjacentTiles){
averageOxygen += go.GetComponent<AtmosPropagation>().oxygen;
}
if(leak == false)
oxygen = averageOxygen / adjacentTiles.Count;
//yield return new WaitForSeconds(5f);
Debug.Log("Oxygen Level of Tile @ " + transform.position.ToString() + " = " + oxygen);
averageOxygen = 0f;
if(oxygen >= 18f)
renderer.material.color = Color.green;
if(oxygen >= 15f && oxygen < 18f)
renderer.material.color = Color.yellow;
if(oxygen > 10f && oxygen < 15f)
renderer.material.color = Color.red;
if(oxygen <= 10f)
renderer.material.color = Color.black;
}
public void CheckForLeaks(){
if((adjacentTiles.Count + adjacentWalls.Count) < 10){
leak = true;
Debug.Log ("Walls: " + adjacentWalls.Count);
if(oxygen < 0)
oxygen = 0;
if(oxygen != 0)
oxygen -= (oxygen * .1f);
}
}
}
Edit: To clarify, this script is on each of my "floor" tiles.
Answer by sparkzbarca · Nov 11, 2012 at 01:41 AM
go.GetComponent().oxygen;
store the component so you stop fetching it constantly.
try breaking up the update, don't update them all at the same time, chain the updates.
all you need to do is have the start value of invoke repeating the first 5. be a random number that is 4.5 + a random value between .1 and .5;
if you have it be .1 or .2 or .3 or .4 or .5 you'll now update them 1/5th each time. (approx of course, its random but on average they should be distributed with 1/5th in each of the five areas given a sufficiently large amount of calls to random) and honestly frames are over faster than 1/10th of a second, normally closer to a 30th of a second. but just for now have that. You'll get 1/5th as much updating happening in the same frame. that should help remove the hiccuping.
That getcomponent is in a foreach loop. So presumably it needs to change every time it iterates through. How would I go about storing the component if it needs to change all the time? Store X amount of separate components?
store it once in an array and iterate through the array ins$$anonymous$$d.
Brilliant. Log solved completely. $$anonymous$$ade a couple similar optimizations after solving the component fetching issue. I have them updating staggered like you suggested, but it's causing so little issue that I could probably even update them all simultaneously now.
Thanks!
Wow I didnt realize getcomponent was that intensive an operation but hey it worked!
Just another point - use a coroutine rather than InvokeRepeating and you can spread the load of your routine over several frames too by sticking a couple of yield return nulls in there.
Your answer
Follow this Question
Related Questions
Unity lag on selection 0 Answers
Practical solutions for lag reduction? 1 Answer
Instantiating a gameobject causes a lagspike 2 Answers
Best way to display scores appearance 1 Answer
Fps Drops with lots of gameObjects 1 Answer