- Home /
Lag when activating GameObjects
I'm doing a simple script of a character running through a dynamically generated track, defined in segments. I have multiple instances of the segments instantiated in Start() with active=false, and have 4 segments active at any point of time.
Everytime the character crosses the end of 1 segment, I will deactivate the segment behind and activate a new segment at the end of the track. When this action takes place, there is a significant lag (1-2s). This lag is reduced to almost nothing when all the segments have been set active=true at least once.
Thinking that all segments must be rendered at least once, I set Update() to have everything active=true when first called, and then as normal from the second time Update() is called. There is a much longer lag at the start (expected) but the lag still remains.
What else can I do to eliminate this lag?
Thanks in advance.
This is the code that calls when the lag occurs. Not very optimized, but am quite sure the non-optimized bits won't cause this kind of lag.
Basically I use the "active" state of the gameobject to deter$$anonymous$$e if it is available to be retrieved from the pool. GameObjectPool contains all the gameobjects that had been instantiated inside Start() and active=false.
$$anonymous$$ain issue is, the lag happens only ONCE for the same code. So if I have 10 road segment instances in the gameobject pool, it would lag 10 different times and subsequent calls will be much smoother.
"Generate Colliders" is unchecked in the imported model, does that mean no physics involved already?
Lag occurs when this is called the first time for each instance. I have run Debug.Log() to ensure that it is run only once inside Update() when supposed to. No accidental repetitions, hopefully.
lastBuilding.transform.parent = null;
lastBuilding.active = false;
lastRoad.active = false;
road = GetGameObject(TrackStraight);
road.transform.position = newPosition;
road.transform.localRotation = roadRotation;
building = GetGameObject(buildingName);
building.transform.parent = road.transform;
building.transform.localRotation = Quaternion.identity;
building.transform.localPosition = Vector3.zero;
building.transform.localScale = Vector3.one;
private GameObject GetGameObject(String resourceRef) {
GameObject[] objList = GameObjectPool[resourceRef];
int i;
// largest objList to be traversed is 4
for (i=0;i<objList.Length;i++) {
GameObject obj = objList[i];
if (obj.active==false) {
obj.active = true;
return obj;
}
}
return null;
}
Sample code to populate GameObjectPool, called once inside Start()
objList = new GameObject[listSize];
int i;
for (i=0;i<listSize;i++) {
obj = (GameObject)Instantiate(Resources.Load("$$anonymous$$odels/"+resourceRef));
obj.active = false;
objList[i] = obj;
}
GameObjectPool[resourceRef] = objList;
Stated in the code that the largest objList is 4, not big I suppose?
Basically, if its the first Inst that lags, why not inst before gameplay starts to initialise your pool?
Answer by loboclerk · Oct 21, 2013 at 03:05 AM
Thanks for everyone's inputs.
After several rounds of tests and alternatives, I'll list my conclusions here. Eventual result was smooth gameplay with additional user input initially.
Enabling and disabling the renderer had the best performance, compared to SetActive() and Instantiate/Destroy.
Lag on the first render of each GameObject instance could not be resolved, so everything had to be rendered first and "covered", while waiting for user to click on a button to start.
I did not have this problem for some time and somehow when I was cleaning up my scripts, it crept in. I've tried all performance tweaks but none of em worked for this. The first lag for an object which renders initially... is it inevitable?
Answer by $$anonymous$$ · Oct 17, 2013 at 01:33 PM
I would take a look at the way you're initializing your track segments. You may have some initialization code inside the Start method for each track segment that's causing the delay. If that's the case, then the delay makes sense since Start only runs if the script instance is enabled.
https://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.Start.html
Does the lag go away once you go through all 4 segments at least once?
Just re-read original question - it looks like the lag indeed goes away, so I would look at your Start() initialization code for each track.
Thanks for your comments. The lag happens when I deactivate 1 segment (and attached children) behind, and activate 1 segment in front. I will also activate some gameobjects (also from a pool), set position/rotation and attach them as child to the main segment.
The code that is being run is exactly the same each time, just that for each instance, the first time takes longer.
Could you post your object activation code from the Update() function? $$anonymous$$aybe you're loading the same track multiple times?
Posted above! Ran Debug.Log() to make sure it wasn't run multiple times. If it did lag due to multiple calls, the lag wouldn't disappear after the first call for each instance?
Answer by meat5000 · Oct 17, 2013 at 01:47 PM
Pre-instantiate and cycle
Enabling and disabling gameobjects is far cheaper than instantiate/destroy. Consider employing an object pool to take advantage of this.
Hi, sorry I did not make it clear above. I am coding my own object pool, that's why I am only activating/deactivating game objects ins$$anonymous$$d of instantiating/destroying them. Unless I'm missing something here? (new to this)
Sounds right. $$anonymous$$aaaaybe time to post some code?
Answer by Chaosgod_Esper · Oct 17, 2013 at 01:59 PM
A 3rd approach is - add your model to a scene and save it from there as a prefab. I recognized that Prefabs are loaded much faster than a direct model (tested in my Dungeon keeper System)
I realize that by calling this, it is working effectively like a prefab. When the script is running, the generated gameobjects are all already indicated as (Clone). The performance difference then would only affect whatever's run in Start() and not in Update().
Instantiate(Resources.Load(resourceRef));
In any case, I tried cloning prefabs explicitly and it was the same.
Answer by whydoidoit · Oct 17, 2013 at 05:15 PM
I'd be guessing you have colliders in there. If the colliders don't have rigidbodies attached then they take a long time to make active at a new location. Attach kinematic rigidbodies to the colliders an it may help.
Actual instances were created inside Start() using
Instantiate(Resources.Load(resourceRef));
Inside Unity Editor, Generate Colliders is unchecked for the imported model. I suppose with this, all physics for these objects would be off already, or am I missing something?
So these sections have to colliders when you look at them in the editor?
I looked at the inspector when the code was running and clicked on the objects in the scene. None of them had any colliders or anything physics related. hmmm..
You are setting and checking .active -> that should now be SetActive and activeInHierarchy presu$$anonymous$$g you are using Unity 4
Thanks for pointing that out. Changed all to SetActive and activeInHierarchy/activeSelf already. No change to performance unfortunately.
Your answer
Follow this Question
Related Questions
Best way to display scores appearance 1 Answer
Instantiate problem 1 Answer
GameObject Instantiated Off Camera 0 Answers