C# Unity3D:从其他类访问时,列表返回null
我目前正试图在unity3D中制作一款小型手机游戏,正如我经常听到的那样,使用实例化/销毁是一种非常糟糕的方式(尽管我从未制作过任何足够大的游戏,但这实际上成为了一个问题),我决定尝试在池系统中制作 我创建了一个脚本,用于处理两个单独列表中的所有池对象。通过从脚本本身调用该方法,我可以成功地从池中生成一个对象,但问题是,当我尝试从另一个脚本调用该方法时,它不起作用。通过不同的尝试,我得到了空引用异常或错误: 由于对象的当前状态,操作无效 System.Linq.Enumerable.First[GameObject](IEnumerable`1源) 我真的找不到其他人有这个问题。而且似乎相关的解决方案也不起作用。主要问题也可能是。。为什么会发生这种情况 池脚本:C# Unity3D:从其他类访问时,列表返回null,c#,list,unity3d,pooling,C#,List,Unity3d,Pooling,我目前正试图在unity3D中制作一款小型手机游戏,正如我经常听到的那样,使用实例化/销毁是一种非常糟糕的方式(尽管我从未制作过任何足够大的游戏,但这实际上成为了一个问题),我决定尝试在池系统中制作 我创建了一个脚本,用于处理两个单独列表中的所有池对象。通过从脚本本身调用该方法,我可以成功地从池中生成一个对象,但问题是,当我尝试从另一个脚本调用该方法时,它不起作用。通过不同的尝试,我得到了空引用异常或错误: 由于对象的当前状态,操作无效 System.Linq.Enumerable.First[
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);
}
}
公共类对象池:单行为{
游戏对象basicCell;
游戏对象基本食物;
私人向量3;
[序列化字段]
私人金额;
[序列化字段]
私人国际食品山;
列出细胞池;
列出foodPool;
游戏对象食物管理器;
游戏对象管理器;
//用于初始化
无效唤醒(){
foodManager=gameObject.transform.FindChild(“FoodPool”).gameObject;
cellManager=gameObject.transform.FindChild(“CellPool”).gameObject;
cellPool=新列表(cellAmount);
foodPool=新列表(foodAmount);
poolSpawnPos=新矢量3(8000,8000,8000);
basicFood=Resources.Load(“Food/basicFood/basicFood”)作为游戏对象;
basicCell=Resources.Load(“单元格/单元格”)作为游戏对象;
对于(int i=0;i0)
//产卵食物(新载体3(0,0,0));
}
公共空间产卵食物(矢量3产卵位置)
{
GameObject selectedFood=null;
selectedFood=foodPool.First();
印刷品(精选食品);
selectedFood.SetActive(true);
foodPool.移除(选定的食物);
selectedFood.transform.parent=null;
selectedFood.transform.position=繁殖位置;
//设定食物统计
}
公共空间食物杀手(游戏对象食物杀手)
{
foodPool.Add(killedFood);
killedFood.transform.position=poolspawnprownpos;
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:MonoBehavior{
公共对象池;
public int initialFoodNumber=50;
无效唤醒()
{
pool=GameObject.Find(“ObjectPool”).GetComponent();
对于(int i=0;i您可以将FoodManager
中的Awake()
更改为Start()
,以确保首先调用ObjectPool
中的代码
或者,您可以显式设置这两个类的脚本执行顺序。这可以通过转到Edit>Project Settings>script execution order
菜单并添加这两个脚本来完成,ObjectPool
的排名高于FoodManager
全部为真。仅就记录而言,这是非常危险的(而且毫无意义)玩弄执行令,这是一个黑客行为。对于这么简单的问题,绝对没有理由这么做。只需使用一个统一事件或从另一个事件中调用一个就行了!对于这样的设置,我现在觉得自己很愚蠢!:)我显然找错地方了!我没注意到我把食品经理的东西放在了醒着的状态下……嗯!醒着在某一点上是必要的,但这不是我最近的改变……只是忘了把它改回原来的状态!现在效果很好,谢谢你的帮助!我会赞成一个叫另一个的想法。如果你有猫依赖它的话Owner要处于特定状态,如果您不能100%确定,您不能仅仅假设它将处于特定状态。很多时候,您在编辑器中运行,一切正常,然后您在设备上运行,并且顺序发生了更改和错误。在我看来,让Owner调用Cat上的init作为参数(通过接口)传递自己是更好的那么,当猫需要它的时候,你可以肯定地知道主人的状态是什么。“FAFASE,我很想听到更多关于你的偏好……我似乎不知道你为什么要把主人送猫作为一个参数。考虑你的猫的行为取决于主人的行为,如果猫是粗心的或是主人的话,猫就会变得流浪。如果主人是一个细心的小女孩,那它就是一只好猫。猫需要知道主人的状态。如果你把主人设置为醒着,猫也在醒着的状态下读取状态,你不能保证主人先完成。但是从主人那里你叫cat.Init(这是IOwnerBehaviour);在醒来的最后,当一切都完成后,你的猫肯定会根据主人的状态进行调整。在评论中很难解释清楚。