【发布时间】: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<>代码作品)。另外我不知道问题出在哪里.. 两个屏幕截图中的镐看起来大致位于相同的位置,但从您的文字来看,我认为问题是所有镐都在某个位置,但是当一个击中墙,他们都搬到了某个“pooler”位置? -
如果我正确理解了您的术语,那么我的单例最初不会以单线程方式调用。对不起,我应该再等几秒钟才能拍第二张截图!不过,我保证,这两个屏幕截图中 PickAxes 的位置是不同的。我很确定这个问题出现在我的 onTriggerEntered 事件函数中,或者出现在我在 PickAxe Spawner 脚本中调用该事件的方式中。 @Quantic
标签: c# unity3d instance pool eventtrigger