Unity3D:从其他 class 访问时列表 returns 为空
Unity3D: List returns null when accessed from other class
我目前正在尝试在 unity3D 中制作一款小型手机游戏,而且我总是听说使用 instantiate/destroy 是一种非常糟糕的方式(尽管我从来没有制作过足够大的游戏一个问题)我决定尝试在池系统中进行。
我创建了一个脚本来处理两个单独列表中的所有合并对象。我可以通过从脚本本身调用方法成功地从池中生成一个对象,但问题是当我尝试从另一个脚本调用该方法时,它不起作用。通过我所做的不同尝试,我得到了空引用异常,或者得到了错误:
Operation is not valid due to the current state of the object
System.Linq.Enumerable.First[GameObject] (IEnumerable`1 source)
我真的找不到其他人遇到这个问题。并且似乎相关的解决方案不起作用。主要问题也可能是……为什么会这样?
池脚本:
public class ObjectPool : MonoBehaviour {
GameObject basicCell;
GameObject basicFood;
private Vector3 poolSpawnPos;
[SerializeField]
private int cellAmount;
[SerializeField]
private int foodAmount;
List<GameObject> cellPool;
List<GameObject> foodPool;
GameObject foodManager;
GameObject cellManager;
// Use this for initialization
void Awake () {
foodManager = gameObject.transform.FindChild ("FoodPool").gameObject;
cellManager = gameObject.transform.FindChild ("CellPool").gameObject;
cellPool = new List<GameObject> (cellAmount);
foodPool = new List<GameObject> (foodAmount);
poolSpawnPos = new Vector3 (8000, 8000, 8000);
basicFood = Resources.Load ("Food/BasicFood/BasicFood") as GameObject;
basicCell = Resources.Load ("Cell/Cell") as GameObject;
for (int i = 0; i < cellAmount; i++) {
GameObject currentCell = Instantiate(basicCell, poolSpawnPos, Quaternion.identity) as GameObject;
currentCell.transform.parent = cellManager.transform;
currentCell.SetActive (false);
cellPool.Add (currentCell);
}
for (int i = 0; i < foodAmount; i++){
GameObject currentFood = Instantiate(basicFood, poolSpawnPos, Quaternion.identity) as GameObject;
currentFood.transform.parent = foodManager.transform;
currentFood.SetActive (false);
foodPool.Add (currentFood);
}
}
// Update is called once per frame
void Update () {
//if(foodPool.Count > 0)
// SpawnFood (new Vector3 (0, 0, 0));
}
public void SpawnFood(Vector3 spawnPosition)
{
GameObject selectedFood = null;
selectedFood = foodPool.First();
print (selectedFood);
selectedFood.SetActive (true);
foodPool.Remove (selectedFood);
selectedFood.transform.parent = null;
selectedFood.transform.position = spawnPosition;
//set food Stats
}
public void KillFood(GameObject killedFood)
{
foodPool.Add (killedFood);
killedFood.transform.position = poolSpawnPos;
killedFood.transform.parent = foodManager.transform;
killedFood.SetActive (false);
}
}
我需要从中调用方法的脚本:
public class FoodManager : MonoBehaviour {
public ObjectPool pool;
public int initialFoodNumber = 50;
void Awake()
{
pool = GameObject.Find("ObjectPool").GetComponent<ObjectPool>();
for (int i = 0; i <= initialFoodNumber; i++)
{
pool.SpawnFood(new Vector3(Random.Range(-40, 41), 0, Random.Range(-40, 41)));
}
}
}
您可以将 FoodManager
中的 Awake()
更改为 Start()
以确保首先调用 ObjectPool
中的代码。
或者您可以明确设置这 2 个 类 的脚本执行顺序。这是通过转到 Edit > Project Settings > Script Execution Order
菜单并添加两个脚本来完成的,ObjectPool
排名在 FoodManager
之上。 Source
我目前正在尝试在 unity3D 中制作一款小型手机游戏,而且我总是听说使用 instantiate/destroy 是一种非常糟糕的方式(尽管我从来没有制作过足够大的游戏一个问题)我决定尝试在池系统中进行。
我创建了一个脚本来处理两个单独列表中的所有合并对象。我可以通过从脚本本身调用方法成功地从池中生成一个对象,但问题是当我尝试从另一个脚本调用该方法时,它不起作用。通过我所做的不同尝试,我得到了空引用异常,或者得到了错误:
Operation is not valid due to the current state of the object System.Linq.Enumerable.First[GameObject] (IEnumerable`1 source)
我真的找不到其他人遇到这个问题。并且似乎相关的解决方案不起作用。主要问题也可能是……为什么会这样?
池脚本:
public class ObjectPool : MonoBehaviour {
GameObject basicCell;
GameObject basicFood;
private Vector3 poolSpawnPos;
[SerializeField]
private int cellAmount;
[SerializeField]
private int foodAmount;
List<GameObject> cellPool;
List<GameObject> foodPool;
GameObject foodManager;
GameObject cellManager;
// Use this for initialization
void Awake () {
foodManager = gameObject.transform.FindChild ("FoodPool").gameObject;
cellManager = gameObject.transform.FindChild ("CellPool").gameObject;
cellPool = new List<GameObject> (cellAmount);
foodPool = new List<GameObject> (foodAmount);
poolSpawnPos = new Vector3 (8000, 8000, 8000);
basicFood = Resources.Load ("Food/BasicFood/BasicFood") as GameObject;
basicCell = Resources.Load ("Cell/Cell") as GameObject;
for (int i = 0; i < cellAmount; i++) {
GameObject currentCell = Instantiate(basicCell, poolSpawnPos, Quaternion.identity) as GameObject;
currentCell.transform.parent = cellManager.transform;
currentCell.SetActive (false);
cellPool.Add (currentCell);
}
for (int i = 0; i < foodAmount; i++){
GameObject currentFood = Instantiate(basicFood, poolSpawnPos, Quaternion.identity) as GameObject;
currentFood.transform.parent = foodManager.transform;
currentFood.SetActive (false);
foodPool.Add (currentFood);
}
}
// Update is called once per frame
void Update () {
//if(foodPool.Count > 0)
// SpawnFood (new Vector3 (0, 0, 0));
}
public void SpawnFood(Vector3 spawnPosition)
{
GameObject selectedFood = null;
selectedFood = foodPool.First();
print (selectedFood);
selectedFood.SetActive (true);
foodPool.Remove (selectedFood);
selectedFood.transform.parent = null;
selectedFood.transform.position = spawnPosition;
//set food Stats
}
public void KillFood(GameObject killedFood)
{
foodPool.Add (killedFood);
killedFood.transform.position = poolSpawnPos;
killedFood.transform.parent = foodManager.transform;
killedFood.SetActive (false);
}
}
我需要从中调用方法的脚本:
public class FoodManager : MonoBehaviour {
public ObjectPool pool;
public int initialFoodNumber = 50;
void Awake()
{
pool = GameObject.Find("ObjectPool").GetComponent<ObjectPool>();
for (int i = 0; i <= initialFoodNumber; i++)
{
pool.SpawnFood(new Vector3(Random.Range(-40, 41), 0, Random.Range(-40, 41)));
}
}
}
您可以将 FoodManager
中的 Awake()
更改为 Start()
以确保首先调用 ObjectPool
中的代码。
或者您可以明确设置这 2 个 类 的脚本执行顺序。这是通过转到 Edit > Project Settings > Script Execution Order
菜单并添加两个脚本来完成的,ObjectPool
排名在 FoodManager
之上。 Source