- Home /
Can't Find Optimization Problem in My Scripts
I have been trying for weeks to get my project running smoothly. It's as simple as it gets. I have set up an object pool and generator so that a few prefabs will move from right to left on the screen at random velocities. No matter what I try, I still get a lot of lag. It must be something simple that I'm missing. It's a simple 2D game with no more than 5 sprites moving at one time. It was working perfectly until a little while ago, and now for no reason it seems to lag terribly. I don't even think I changed these scripts. PLEASE if you have any idea why, let me know. Note that I have a box collider at the left edge of the screen (set as trigger) to detect when to disable the objects. I didn't include that because its obvious how it should be done.
Generator.cs
using UnityEngine;
using System.Collections;
public class Generator : MonoBehaviour
{
public ObjectPooler asteroidPool;
private float _createPosX;
private float _startDelay;
void Awake()
{
_createPosX = 15.0f;
_startDelay = 1.0f;
}
void Start ()
{
StartCoroutine( GenerateAsteroids() );
}
IEnumerator GenerateAsteroids()
{
// Delay generation in the beginning of the game.
yield return new WaitForSeconds( _startDelay );
GameObject newAsteroid;
float posY;
float speed;
float angVel;
// Loop forever
while( true )
{
// Randomize attributes of our new asteroid.
posY = Random.Range( -5.0f, 5.0f );
speed = Random.Range( 3.0f, 5.0f );
angVel = Random.Range( -50.0f, 50.0f );
// Select a prefab from our object pool and set it to active.
newAsteroid = asteroidPool.GetPooledObject();
newAsteroid.SetActive( true );
// Cache a reference to the new asteroid's rigidbody component.
Rigidbody2D rb = newAsteroid.GetComponent<Rigidbody2D>();
// Cache a reference to the new asteroid's transform component.
Transform newTransform = newAsteroid.transform;
// Apply the appropriate speed, position, etc. to the asteroid.
newTransform.position = new Vector2( _createPosX, posY );
rb.velocity = Vector2.left * speed;
rb.angularVelocity = angVel;
// Generate a new asteroid after the given amount of time.
yield return new WaitForSeconds( 2.2f );
}
}
}
ObjectPooler.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPooler : MonoBehaviour
{
public GameObject pooledObject;
public int pooledAmount;
private List<GameObject> _pooledObjects;
private Transform _poolerTransform;
void Awake()
{
_pooledObjects = new List<GameObject>();
_poolerTransform = transform;
}
void Start()
{
for( int i = 0; i < pooledAmount; i++ )
{
GameObject go = Instantiate( pooledObject );
go.transform.parent = _poolerTransform;
go.SetActive( false );
_pooledObjects.Add( go );
}
}
public GameObject GetPooledObject()
{
// Cycle through all of our pooled objects...
for( int i = 0; i < _pooledObjects.Count; i++ )
{
// If we find an object in our pool that is inactive...
if( !_pooledObjects[i].activeInHierarchy )
{
// Return this game object.
return _pooledObjects[i];
}
}
// If we didn't find an available object in our pool, instantiate a new one.
GameObject go = Instantiate( pooledObject );
go.transform.parent = _poolerTransform;
go.SetActive( false );
_pooledObjects.Add( go );
return( go );
}
public void ResetPool()
{
foreach( GameObject go in _pooledObjects )
{
go.SetActive( false );
}
}
}
It may be prudent to clarify exactly what you mean when you use the term "lag" -- Lag primarily refers to the delay between a client and a server for a computer-to-computer/server connection.
I assume you're referring to either of:
Input lag: You press a key, then the visible response on screen occurs a moment later, making competent control over the character nearly impossible.
Low frame rate: Performance is suffering, so if the game is running poorly enough, it may appear to be little more than a vaguely-interactive slideshow.
Anyway, without a clearer picture of what problem is referred to as "lag" it is challenging to provide insight on the actual cause.
By lag I mean the framerate drops every 1-2 seconds, causing a jitter/stutter in the motion of objects moving across the screen. In other words, the objects don't move smoothly.
Does the game start lagging right after you start the game or after playing for a while.
As soon as you open the game and as long as it runs.
Answer by tanoshimi · Mar 02, 2016 at 08:20 PM
Use Unity's built-in profiler to find out exactly what is taking the time in each frame.
Already did. It says its Graphics.PresentAndSync takes up the most resources. But I also get spikes from this on an empty scene... Also the graphics I'm testing this on are just squares. No transparency or anything. So if that were the source of the lag I don't see how Unity could feasibly be used for any kind of development.
Answer by Jessespike · Mar 02, 2016 at 09:03 PM
it's the Instantiate that happens every 2.2s in the coroutine. Also the point of an object pool is so you do not have to continuously instantiate new objects.
Where do you see that? The only time an instantiate can happen after starting up these scripts is if the object pool needs more than the 5 initial prefabs that are instantiated, which never really happens... Please do correct me if I'm wrong though. That could definitely be the source of the problem!
I copy-pasted these scripts, threw in a cube prefab with a 2d rigid body and let it run. These scripts continuously instantiate for me. Perhaps its not the instantiate call specifically for the frame rate drop, but rather the deactivating and activating of physics objects that are called immediately afterwards.
That may be because I did not include my script for deactivating the pooled objects above. As I said in my post, the way I do this is to have an empty game object with a box collider set as a trigger. Then anytime a rigidbody with a collider passes through this area, its gameobject is set to inactive. If you did not do this step, then yes the script above would continuously instantiate more and more prefabs because it can't find any in the pool that are disabled. Thank you for all your help though! What exactly do you mean by, "Perhaps its not the instantiate call specifically for the frame rate drop, but rather the deactivating and activating of physics objects that are immediately called"?
The prefab has a rigid body (physics component). Generator calls GetPooledObjects and then calls SetActive(true), but inside of GetPooledObjects() right after the Instantiate, there is a call to SetActive(false). it just seems unnecessary.
Answer by DuckWare Games · Mar 03, 2016 at 03:20 PM
Try running Profiler to see what is causing the problem. Also as i saw on your script you are using foreach loop something that according to this is slowing the CPU. What about your sprites are you using one sprite for every element on your scene or is the resolution too high? A screenshot of Profiler would be great to understand in depth what causes the lag.
Check out Unity Documentation for more tips: Here
OR
Check out this blog as it has some good tips: Here
Answer by dan5071 · Mar 02, 2016 at 10:33 PM
Finally figured out was was wrong!!! Had nothing to do with my scripts at all... I must have been messing with some project settings and turned VSync off. Now that I turned it back on it's smooth as butter. Thanks to all of you who were willing to offer your help!
Your answer
Follow this Question
Related Questions
Rigidbody 2D Jittery 2 Answers
Why does this simple follow script make my game lag? 2 Answers
Public, private and getting stuff efficiency question. 2 Answers
Multiplayer Clients Jitter On Moving Platform? 1 Answer
Game "laggy" at 30FPS smooth on 60 2 Answers