我在Unity3D中构建游戏,我试图通过启用和禁用它们来重用GameObjects,而不是实例化和销毁它们。移动/移动数组中的对象,然后将第一个元素移动到最后一个索引
我在GameObject数组中有10个弹簧,每当我使用弹簧时,我想从数组中的第一个元素中取出它,将该数组的所有剩余元素向上移动,然后将第一个对象移动到数组中的最后一个索引。
我在Unity3D中构建游戏,我试图通过启用和禁用它们来重用GameObjects,而不是实例化和销毁它们。移动/移动数组中的对象,然后将第一个元素移动到最后一个索引
我在GameObject数组中有10个弹簧,每当我使用弹簧时,我想从数组中的第一个元素中取出它,将该数组的所有剩余元素向上移动,然后将第一个对象移动到数组中的最后一个索引。
这被称为对象池。您不需要从第一个或最后一个移除数组来执行此操作。有很多方法可以在Unity中对其进行归档。
方法1(推荐):
即使这样的作品,它不必要和低效移动的对象在数组中。你可以有一个移动的索引。它从0
开始,每次您请求一个对象时,都会将其加1。如果索引等于Array.Length - 1
,则将索引重置为0
。
public class ArrayObjectPooling
{
int amount = 10;
GameObject[] objArray;
int currentIndex = 0;
public ArrayObjectPooling(GameObject objPrefab, string name, int count)
{
amount = count;
objArray = new GameObject[amount];
for (int i = 0; i < objArray.Length; i++)
{
objArray[i] = UnityEngine.Object.Instantiate(objPrefab, Vector3.zero, Quaternion.identity);
objArray[i].SetActive(false);
objArray[i].name = name + " #" + i;
}
}
//Returns available GameObject
public GameObject getAvailabeObject()
{
//Get the first GameObject
GameObject firstObject = objArray[currentIndex];
//Move the pointer down by 1
shiftDown();
return firstObject;
}
//Returns How much GameObject in the Array
public int getAmount()
{
return amount;
}
//Moves the current currentIndex GameObject Down by 1
private void shiftDown()
{
if (currentIndex < objArray.Length - 1)
{
currentIndex++;
}
else
{
//Reached the end. Reset to 0
currentIndex = 0;
}
}
}
用法:
public GameObject prefab;
void Start()
{
ArrayObjectPooling arrayPool = new ArrayObjectPooling(prefab, "Springs", 10);
GameObject myObj = arrayPool.getAvailabeObject();
}
方法2:
List
就足以做到这一点如果池小。请致电take查看Unity的Object Pooling官方教程。这里不需要发布代码。
您只需禁用游戏对象在List
回收它。下次需要一个新的时候,循环List
并返回List
中第一个禁用的游戏对象。如果启用,这意味着它仍在使用中。
如果在List
中找不到禁用的游戏对象,则可以将Instantiate
一个新的,添加到列表中,然后返回它。这是做这件事最简单的方法。只需观看Unity教程以获取更多信息。
方法3:
使用队列或堆栈。您可以排队并排队或推送/弹出池中的对象。如果您在这方面进行简单的研究 - 搜索,那么有很多实现。
方法4:
这只是提到,因为这是你如何转变对象的数组起来,然后把第一个值在数组的最后一个索引原来的问题。你不应该使用这个。这里只是为了表明它可以可以完成。
public class ArrayObjectPooling
{
int amount = 10;
public GameObject[] objArray;
public ArrayObjectPooling(GameObject objPrefab, string name, int count)
{
amount = count;
objArray = new GameObject[amount];
for (int i = 0; i < objArray.Length; i++)
{
objArray[i] = UnityEngine.Object.Instantiate(objPrefab, Vector3.zero, Quaternion.identity);
objArray[i].SetActive(false);
objArray[i].name = name + " #" + i;
}
}
//Returns available GameObject
public GameObject getAvailabeObject()
{
//Get the first GameObject
GameObject firstObject = objArray[0];
//Move everything Up by one
shiftUp();
return firstObject;
}
//Returns How much GameObject in the Array
public int getAmount()
{
return amount;
}
//Moves the GameObject Up by 1 and moves the first one to the last one
private void shiftUp()
{
//Get first GameObject
GameObject firstObject = objArray[0];
//Shift the GameObjects Up by 1
Array.Copy(objArray, 1, objArray, 0, objArray.Length - 1);
//(First one is left out)Now Put first GameObject to the Last one
objArray[objArray.Length - 1] = firstObject;
}
}
用法:
public GameObject prefab;
void Start()
{
ArrayObjectPooling arrayPool = new ArrayObjectPooling(prefab, "Springs", 3);
GameObject myObj = arrayPool.getAvailabeObject();
}
是的想过,但不想检查GameObjects是否启用。认为可能有某种类型的数组或列表中的操作只是将GameObject引发到数组/列表的末尾。这样我就可以每次使用数组中的第一个游戏对象,没有检查 – LooMeenin
我以前见过那个教程,我过去使用过对象池,但是我认为这种场景我更喜欢使用数组或列表某种具有我描述的操作的东西。如果没有这样的操作,那么我会找出其他的东西。 – LooMeenin
@LooMeenin **我试图通过启用和禁用它们来重用GameObjects,而不是实例化和销毁它们。**现在您说您不想检查它们是否启用/禁用?为什么甚至打扰首先启用/禁用它们?你想使用数组,如果你需要超过10个弹簧呢?他们在比赛中是否永远保证10? – Programmer
为什么不使用,在此添加禁用的元素队列,并在需要的时候,你从它出队获得以前禁用的情况下,仅需要被重新启用。为什么是数组? – ray
@ray - 不知道,只是认为它可能有一个操作来做我正在做的事!之前从未使用过队列。 – LooMeenin
@LooMeenin:您应该检查文档,看看在尝试编写代码之前,类是否提供您正在查找的操作,以便发现情况并非如此。如果你之前从未使用过队列(这是一个基本的数据结构),那么在深入研究或了解游戏编程之前,你可能需要更好地理解一些基础知识。 – ray