Reputation: 450
I have ran into a sort of a problem in my project, I am creating a Scroll listview to show all elements present in list in screen. I am using button in panel to show list. Now When I call ShowList() it shows elements in the list.
But if i add some objects to list and again call ShowList() then it also make clone of previous object as instantiated objects are present.
To solve this I am deleting clones using Destroy() but when list contain too many item (300~400) deleting them cause lag in the game . How can I create object pool for ui button or just deactivate them.
public class two : MonoBehaviour {
public GameObject Button_Template;
private List<GameName> gm = new List<GameName>();
public void Exit()
{
var og = GameObject.FindGameObjectsWithTag("clone");
for (int i = 0; i < og.Length; i++)
{
Destroy(og[i]);
}
}
void Start()
{ gm.Add(new GameName("1"));
gm.Add(new GameName("2"));
gm.Add(new GameName("3"));
gm.Add(new GameName("4"));
}
public void ShowList()
{
for (int i = 0 ; i < gm.Count; i++)
{
GameObject go = Instantiate(Button_Template) as GameObject;
go.SetActive(true);
one TB = go.GetComponent<one>();
TB.SetName(gm[i].GName);
go.transform.SetParent(Button_Template.transform.parent);
go.tag = "clone";
}
}
}
Upvotes: 1
Views: 2055
Reputation: 125275
List can be used to implement Object Pooling. Simply disable
the GameObject when you are done using it. Re-enable it again if you want to use it again. The simple GameObject Pool script below re-implements the Instantiate
and Destroy
functions.
public class BUTTONPOOL : MonoBehaviour
{
GameObject buttonPrefab;
List<GameObject> buttonPool;
bool ready = false;
public void createButtonPool(GameObject buttonPrefab, int amount = 400)
{
if (ready)
{
Debug.LogError("createButtonPool can only be called once");
return;
}
this.buttonPrefab = buttonPrefab;
//Create 400 Buttons
buttonPool = new List<GameObject>();
for (int i = 0; i < amount; i++)
{
buttonPool.Add(Instantiate(this.buttonPrefab) as GameObject);
}
ready = true;
}
//Creates/Enables single Button
public GameObject Instantiate()
{
if (!ready)
{
showError();
return null;
}
//Return any Button that is not active
for (int i = 0; i < buttonPool.Count; i++)
{
if (!buttonPool[i].activeSelf)
{
return buttonPool[i];
}
}
//Create new Button if there is none available in the pool. Add it to the list then return it
GameObject tempButton = Instantiate(this.buttonPrefab) as GameObject;
buttonPool.Add(tempButton);
return tempButton;
}
//Destroys/Disables single Button
public void Destroy(GameObject button)
{
if (!ready)
{
showError();
return;
}
button.SetActive(false);
}
//Destroys/Disables all Buttons
public void DestroyAll()
{
if (!ready)
{
showError();
return;
}
for (int i = 0; i < buttonPool.Count; i++)
{
if (buttonPool[i].activeSelf)
{
buttonPool[i].SetActive(false);
}
}
}
private void showError()
{
Debug.LogError("createButtonPool must be called once before any other function can be called");
}
}
Usage:
public GameObject ButtonPrefab;
BUTTONPOOL bPool;
void test()
{
if ((bPool = GetComponent<BUTTONPOOL>()) == null)
{
gameObject.AddComponent<BUTTONPOOL>();
bPool = GetComponent<BUTTONPOOL>();
}
//Initiate with 300 Buttons
bPool.createButtonPool(ButtonPrefab, 50);
GameObject tempButton = bPool.Instantiate();
//MUST SET BUTTON ACTIVE CALLING Instantiate()
tempButton.SetActive(true);
//You can do other things with the button
one TB = tempButton.GetComponent<one>();
//To destroy that single button
bPool.Destroy(tempButton);
//OR destroy that all button
bPool.DestroyAll();
}
Note that you must set the Button
to active after calling the custom Instantiate()
function from the BUTTONPOOL
script.
Upvotes: 1