问题
例如我在对象池中需要从 Perfab 创建物体,然后我需要这个物体的父对象是某个特定物体
具体到我的场景中,我需要这个物体的父对象拥有 Canvas,因为这个物体的脚本中的 Start 需要获取 Canvas
因此我希望把这个对象池放到 Canvas 下面,然后希望这个物体刚生成的时候就以对象池作为父级
如果在 Instantiate 函数中不指定父对象,那么新创建的物体默认会放在当前激活场景的根目录
我使用的第一种更改父对象的方法会报错,使用的第二种不会报错,因此记录一下
脚本
对象池的脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Universal
{
public class ObjectsPool : MonoBehaviour
{
[SerializeField] private GameObject prefab;
private Queue<GameObject> pooledInstanceQueue = new Queue<GameObject>();
public GameObject GetInstance()
{
if (pooledInstanceQueue.Count > 0)
{
GameObject instanceToReuse = pooledInstanceQueue.Dequeue();
instanceToReuse.SetActive(true);
return instanceToReuse;
}
else
{
// 默认父对象为 Pool
GameObject instance = Instantiate(prefab, transform);
// 默认父对象为 Pool
// instance.transform.SetParent(gameObject.transform);
return instance;
}
}
public void ReturnInstance(GameObject gameObjectToPool)
{
pooledInstanceQueue.Enqueue(gameObjectToPool);
gameObjectToPool.SetActive(false);
}
}
}
其中存在差异的是
// 默认父对象为 Pool
GameObject instance = Instantiate(prefab, transform);
// 默认父对象为 Pool
// instance.transform.SetParent(gameObject.transform);
return instance;
第一种方法是 Instantiate(prefab, transform); 这个是生成的时候就设置了父对象是对象池
第二种方法是先以当前激活场景的根节点为父对象,然后再移动到对象池为父对象
实践中发现,第二种方法中,被创建的物体的 Start 会先于 instance.transform.SetParent(gameObject.transform); 调用,那么新创建的物体在进行 Start 方法时父对象还是当前激活场景的根节点,那么 Start 方法中具体的逻辑在获取一些物体,比如获取 Canvas 时就会报错