如何使用对象池在x,y,z上放置随机对象?

时间:2019-02-25 22:40:17

标签: c# unity3d

我有两个脚本,每个脚本都附加到另一个空的GameObject:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPooler : MonoBehaviour
{
    [System.Serializable]
    public class Pool
    {
        public string tag;
        public GameObject prefab;
        public int size;
    }

    #region Singleton

    public static ObjectPooler Instance;

    private void Awake()
    {
        Instance = this;
    }

    #endregion

    public List<Pool> pools;
    public Dictionary<string, Queue<GameObject>> poolDictionary;

    // Start is called before the first frame update
    void Start()
    {
        poolDictionary = new Dictionary<string, Queue<GameObject>>();

        foreach(Pool pool in pools)
        {
            Queue<GameObject> objectPool = new Queue<GameObject>();

            for(int i = 0; i < pool.size; i++)
            {
                GameObject obj = Instantiate(pool.prefab);
                obj.SetActive(false);
                objectPool.Enqueue(obj);
            }

            poolDictionary.Add(pool.tag, objectPool);
        }
    }

    public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)
    {
        if(!poolDictionary.ContainsKey(tag))
        {
            Debug.LogWarning("Pool with tag " + tag + " doesn't exist.");
            return null;
        }

        GameObject objectToSpawn = poolDictionary[tag].Dequeue();

        objectToSpawn.SetActive(true);
        objectToSpawn.transform.position = position;
        objectToSpawn.transform.rotation = rotation;

        IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();

        if(pooledObj != null)
        {
            pooledObj.OnObjectSpawn();
        }

        poolDictionary[tag].Enqueue(objectToSpawn);

        return objectToSpawn;
    }
}

第二个,这里我在FixedUpdate中添加了随机部分:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeSpawner : MonoBehaviour
{
    ObjectPooler objectPooler;

    // Start is called before the first frame update
    void Start()
    {
        objectPooler = ObjectPooler.Instance;
    }

    private void FixedUpdate()
    {
        var randp = new Vector3(Random.Range(0, 300), Random.Range(0, 300), Random.Range(0, 300));
        objectPooler.SpawnFromPool("Cube", randp, Quaternion.identity);
    }
}

到目前为止,它可以满足我的要求,但是我是否将随机部分添加到了正确的脚本中并放置了?

我该如何使它代替生成不间断的随机对象,而仅在更改size变量的Range滑块时才生成它们呢?

例如[Range(1,150])

当我更改值时,它将在FixedUpdate中添加/删除对象吗? (应该是Update,它是FixedUpdate,因为在此之前我使用了Rigidbody,但现在没有使用)。

想法是更改大小,或者如果我将大小设置为1000,然后使用“范围”滑块更改使用对象的数量,例如445或500或1000。

每次更改大小时,它会将对象随机放在其他随机位置。但是一次,而不是像现在在固定更新中那样总是如此。

每次更改大小都会随机更改对象位置。 因此,如果将大小更改为10,则随机更改10个对象的位置,并仅使用这10个对象。如果我将大小更改为700,则随机重新放置700个对象并使用700。(不确定使用还是销毁是正确的。)

更新:

这是我在添加oldSize变量和Range的第一个脚本中尝试的操作:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPooler : MonoBehaviour
{
    [System.Serializable]
    public class Pool
    {
        public string tag;
        public GameObject prefab;
        [Range(1, 150)]
        public int size;
        public int sizeOld;
    }

    #region Singleton

    public static ObjectPooler Instance;

    private void Awake()
    {
        Instance = this;
    }

    #endregion

    public List<Pool> pools;
    public Dictionary<string, Queue<GameObject>> poolDictionary;

    // Start is called before the first frame update
    void Start()
    { 
        poolDictionary = new Dictionary<string, Queue<GameObject>>();

        foreach(Pool pool in pools)
        {
            Queue<GameObject> objectPool = new Queue<GameObject>();

            for(int i = 0; i < pool.size; i++)
            {
                GameObject obj = Instantiate(pool.prefab);
                obj.SetActive(false);
                objectPool.Enqueue(obj);
            }

            poolDictionary.Add(pool.tag, objectPool);
        }
    }

    private void Update()
    {

    }

    public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)
    {
        if(!poolDictionary.ContainsKey(tag))
        {
            Debug.LogWarning("Pool with tag " + tag + " doesn't exist.");
            return null;
        }

        GameObject objectToSpawn = poolDictionary[tag].Dequeue();

        objectToSpawn.SetActive(true);
        objectToSpawn.transform.position = position;
        objectToSpawn.transform.rotation = rotation;

        IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();

        if(pooledObj != null)
        {
            pooledObj.OnObjectSpawn();
        }

        poolDictionary[tag].Enqueue(objectToSpawn);

        return objectToSpawn;
    }
}

在“开始”的第二个脚本中,例如,我使用了整个对象一次,当Range值为27时启动了游戏,然后在更改值时更新了oldSize:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeSpawner : MonoBehaviour
{
    ObjectPooler objectPooler;

    // Start is called before the first frame update
    void Start()
    {
        objectPooler = ObjectPooler.Instance;

        foreach (ObjectPooler.Pool pool in objectPooler.pools)
        {
            var randp = new Vector3(Random.Range(0, 300), Random.Range(0, 300), Random.Range(0, 300));
            objectPooler.SpawnFromPool("Cube", /*transform.position*/ randp, Quaternion.identity);
        }
    }

    private void Update()
    {
        foreach (ObjectPooler.Pool pool in objectPooler.pools)
        {
            if (pool.size != pool.sizeOld)
            {
                int diff = pool.size - pool.sizeOld;
                pool.sizeOld = pool.size;

                // Spawn new diff number of objects if diff is positive
                var randp = new Vector3(Random.Range(0, 300), Random.Range(0, 300), Random.Range(0, 300));
                objectPooler.SpawnFromPool("Cube", /*transform.position*/ randp, Quaternion.identity);
            }
        }
        //var randp = new Vector3(Random.Range(0, 300), Random.Range(0, 300), Random.Range(0, 300));
        //objectPooler.SpawnFromPool("Cube", transform.position /*randp*/, Quaternion.identity);
    }
}

但是事实上,希拉里的生成器从未改变过,一直存在27个。如果Range小于27,它将使用较少的对象,但是如果范围大于27,仍然在层次结构中,则只有27个生成器。 / p>

生成器的大小永远不会改变。然后,当将范围右移到右时,将使生成器使用它们直到结束,就是这样,它将永远不会改变,它将使用它们,仅使用27。

例如,即使Range值是150,在等级中仍然有27个生成器,并且在游戏中它本身是150,而不是150。

1 个答案:

答案 0 :(得分:0)

  

到目前为止,它可以满足我的要求,但是我是否在正确的脚本中添加了随机部分并放置了?

我不知道,如果你问我是1 +1 = 2,我可以给你答案。

  

我该如何使它生成连续的随机对象,而不是生成连续的随机对象,仅当我更改大小变量的“范围”滑块时才生成它们?

您需要另一个尺寸字段:

public class Pool
{
    public string tag;
    public GameObject prefab;
    [Range(1, 150)]
    public int size;
    private int sizeOld;
}

然后在FixedUpdate更新中进行简单比较:

void Update()
{
    foreach(Pool pool in pools)
    {
        if(pool.size != pool.sizeOld)
        {
            int diff = pool.size - pool.sizeOld;
            pool.sizeOld = pool.size;

            // Spawn new diff number of objects if diff is positive
        }
    }
}
  

当我更改值时,它将在FixedUpdate中添加/删除对象?

取决于调用生成方法的位置。