【问题标题】:Why Do My Obstacles Do This In My Object Pooler?为什么我的障碍物在我的对象池中这样做?
【发布时间】:2016-11-09 03:12:18
【问题描述】:

我的 PickAxe 游戏对象的对象池系统几乎完成了,但我有一个问题需要帮助。

我想弄清楚为什么每当第一个 PickAxe 撞到墙上时我的所有产卵都会重新开始?每当 PickAxe 撞到墙上时,我如何才能回到“pooler”中?

我拍了两张截图,我也会在下面发布我的代码。第一个是在生成的第一个 Pickaxe 撞到墙上之前,第二个屏幕截图是在同一个 PickAxe 撞到墙上之后。

下面是我的一些代码:

这个脚本产生了我的 PickAxes。我 99% 确定我的问题是我在 CoRoutine 中调用事件函数的位置。我说的对吗?

using UnityEngine;
using System.Collections;

[System.Serializable]

public class Obstacle4 // Pick Axe Obstacle
{
    public float SpawnWait; // Time in seconds between next wave of obstacle 4.
    public float StartGameWait; // Time in seconds between when the game starts and when the fourth obstacle start spawning.
    public float WaveSpawnWait; // Time in seconds between waves when the next wave of obstacle 4 will spawn.
}

public class SpawnPickAxe : MonoBehaviour 
{

    public GameObject pickAxePrefab;

    public Obstacle4 obstacle4_;

    void Start () 
    {

        PickAxePoolManager.instance.CreatePool (pickAxePrefab, 15); //CreatePool is a method in PickAxePoolManager

        StartCoroutine (PickAxeSpawner ());
    }


    IEnumerator PickAxeSpawner () 
    {

        yield return new WaitForSeconds (obstacle4_.StartGameWait);
        while (true) 
        {

            for (int i = 0; i < 5; i++) 
            {

                Vector3 newSpawnPosition = new Vector3 (Random.Range(-10.0f, 10.0f), 1.2f, 30.0f);
                Quaternion newSpawnRotation = Quaternion.Euler (0.0f, -90.0f, 0.0f);     
                PickAxePoolManager.instance.ReuseObject (pickAxePrefab, newSpawnPosition, newSpawnRotation); //ReuseObject is also a method in PickAxePoolManager
                //Instantiate (obstacle4.pickAxe, spawnPosition, spawnRotation);
                yield return new WaitForSeconds (obstacle4_.SpawnWait);

                ResetByWall.instance.onTriggerEntered += delegate(GameObject obj) 
                {
                    PickAxePoolManager.instance.ReuseObject(pickAxePrefab, newSpawnPosition, newSpawnRotation);
                };
            }
            yield return new WaitForSeconds (obstacle4_.WaveSpawnWait);
        }

    }

}

下面是我的“ResetByWall”脚本。这个脚本也很重要,因为它包含公共事件,允许我检测与我的墙碰撞的任何东西的碰撞,我的墙是触发器。

using System;
using UnityEngine;
using System.Collections;

public class ResetByWall : MonoBehaviour 
{

    //public bool collided;

    //public GameObject pickAxePrefab;

    //NOTE:
    //Singleton Pattern from lines 12 to 25 //
    // ************************************

    static ResetByWall _instance; // Reference to the Reset By Wall script

    public static ResetByWall instance  // This is the accessor
    {
        get 
        {
            if(_instance == null)   // Check to see if _instance is null
            {
                _instance = FindObjectOfType<ResetByWall>(); //Find the instance in the Reset By Wall script in the currently active scene
            }

            return _instance;
        }
    }

    public event Action <GameObject> onTriggerEntered;

    void OnTriggerEnter(Collider other)
    {
        if (onTriggerEntered != null) {
            onTriggerEntered (other.gameObject);
        }
    }
}

下面是我的 PoolManager 脚本。你甚至可能不需要看这个脚本,但我还是会发布它以防万一。

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

public class PickAxePoolManager : MonoBehaviour {

    Dictionary<int,Queue<GameObject>> poolDictionary = new Dictionary<int,Queue<GameObject>>();

    //NOTE: 
    //Singleton Pattern used from lines 12 to 25

    static PickAxePoolManager _instance; // Reference to the Pool Manager script

    public static PickAxePoolManager instance   // This is the accessor
    {
        get 
        {
            if(_instance == null)   // Check to see if _instance is null
            {
                _instance = FindObjectOfType<PickAxePoolManager>(); //Find the instance in the Pool Manager script in the currently active scene
            }

            return _instance;
        }
    }

    /// <summary>
    /// Creates the pool.
    /// </summary>
    /// <param name="prefab">Prefab.</param>
    /// <param name="poolSize">Pool size.</param>

    public void CreatePool(GameObject prefab, int poolSize)
    {
        int poolKey = prefab.GetInstanceID ();  // Unique integer for every GameObject

        if (!poolDictionary.ContainsKey (poolKey))   //Make sure poolKey is not already in the Dictionary, 
            //if it's not then we can create the pool 
        {
            poolDictionary.Add(poolKey, new Queue<GameObject>());

            for (int i = 0; i < poolSize; i++)  //Instantiate the prefabs as dictated by the "poolSize" integer
            {
                GameObject newObject = Instantiate (prefab) as GameObject;  //Instantiate as a GameObject
                newObject.SetActive(false);  // Don't want it to be visible in the scene yet
                poolDictionary [poolKey].Enqueue(newObject);    // Add it to our Pool
            }
        }
    }

【问题讨论】:

  • 你的单例最初是用单线程方式调用的吗?因为有一个竞争条件,多个线程可以在你的if(_instance == null) 上获得true,所以每个线程都会在块内运行代码(我不知道这是否是一个问题,这取决于你的FindObjectOfType&lt;&gt; 代码作品)。另外我不知道问题出在哪里.. 两个屏幕截图中的镐看起来大致位于相同的位置,但从您的文字来看,我认为问题是所有镐都在某个位置,但是当一个击中墙,他们都搬到了某个“pooler”位置?
  • 如果我正确理解了您的术语,那么我的单例最初不会以单线程方式调用。对不起,我应该再等几秒钟才能拍第二张截图!不过,我保证,这两个屏幕截图中 PickAxes 的位置是不同的。我很确定这个问题出现在我的 onTriggerEntered 事件函数中,或者出现在我在 PickAxe Spawner 脚本中调用该事件的方式中。 @Quantic

标签: c# unity3d instance pool eventtrigger


【解决方案1】:

我解决了这个问题。我将在我的 ResetByWall 脚本中使用它:

void OnTriggerEnter (Collider obstacle)
    {
        if (obstacle.gameObject.tag == "Pick Axe")
        {
            obstacle.gameObject.SetActive (false);
        }
    }

谢谢! :)

【讨论】:

  • 使用obstacle.gameObject.CompareTag("Pick Axe")而不是obstacle.gameObject.tag == "Pick Axe",CompareTag 函数具有内置优化和compiles to fewer instructions
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
  • 2017-12-29
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
相关资源
最近更新 更多